saucy 0.12.0 → 0.12.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ 0.12.1
2
+
3
+ * Add configuration options for trial length and the corresponding notification emails.
4
+
1
5
  0.12.0
2
6
 
3
7
  * Add a dependency on Airbrake for exception notification.
data/README.md CHANGED
@@ -128,6 +128,12 @@ You can override all the views by generating them into your app and customizing
128
128
 
129
129
  rails g saucy:views
130
130
 
131
+ You can also customize the default trial length of 30 days, and the timing of expiration notification emails:
132
+
133
+ * Saucy::Configuration.trial_length - An integer. The length of the trial in days.
134
+ * Saucy::Configuration.unactivated_notice_on - An integer. The day of the trial in which the unactivated notice should be sent.
135
+ * Saucy::Configuration.expiring_notice_on - An integer. The number of days remaining that the expiration warning notice should be sent on.
136
+
131
137
  ## Gotchas
132
138
 
133
139
  Make sure you don't do this in ApplicationController:
@@ -14,11 +14,11 @@ en:
14
14
  billing_mailer:
15
15
  expiring_trial:
16
16
  greeting: Thanks for giving us a try!
17
- expiration_notice: "Your 30 day trial for %{account_name} is expiring soon. I hope that you've enjoyed %{app_name} enough to sign up for a paid subscription. If you'd like to continue using your account, please take a moment to choose a paid plan:"
17
+ expiration_notice: "Your trial for %{account_name} is expiring soon. I hope that you've enjoyed %{app_name} enough to sign up for a paid subscription. If you'd like to continue using your account, please take a moment to choose a paid plan:"
18
18
  contact: "If you need more time to evaluate %{app_name} or you have any questions, please don't hesitate to contact me."
19
19
  completed_trial:
20
20
  greeting: Thanks for giving us a try!
21
- notice: "Your 30 day trial for %{account_name} is over, and your account has become inactive. If you'd like to continue using your account, please take a moment to choose a paid plan:"
21
+ notice: "Your trial for %{account_name} is over, and your account has become inactive. If you'd like to continue using your account, please take a moment to choose a paid plan:"
22
22
  contact: "If you need more time to evaluate %{app_name} or you have any questions, please don't hesitate to contact me."
23
23
  new_unactivated:
24
24
  body: |-
data/lib/saucy/account.rb CHANGED
@@ -76,7 +76,7 @@ module Saucy
76
76
  number_free_days = if coupon
77
77
  30 * coupon.free_months
78
78
  else
79
- 30
79
+ Saucy::Configuration.trial_length
80
80
  end
81
81
  self.trial_expires_at = number_free_days.days.from_now(created_at || Time.zone.now)
82
82
  end
@@ -141,11 +141,11 @@ module Saucy
141
141
  def trial_expiring
142
142
  trial.
143
143
  where(:notified_of_expiration => false).
144
- where(["accounts.trial_expires_at <= ?", 7.days.from_now])
144
+ where(["accounts.trial_expires_at <= ?", Saucy::Configuration.expiring_notice_on.days.from_now])
145
145
  end
146
146
 
147
147
  def new_unactivated
148
- where(["accounts.created_at <= ?", 7.days.ago]).
148
+ where(["accounts.created_at <= ?", Saucy::Configuration.unactivated_notice_on.days.ago]).
149
149
  where(:asked_to_activate => false, :activated => false)
150
150
  end
151
151
 
@@ -8,6 +8,9 @@ module Saucy
8
8
  cattr_accessor :merchant_account_id
9
9
  cattr_accessor :admin_username
10
10
  cattr_accessor :admin_password
11
+ cattr_accessor :trial_length
12
+ cattr_accessor :expiring_notice_on
13
+ cattr_accessor :unactivated_notice_on
11
14
 
12
15
  def initialize
13
16
  @@manager_email_address = 'manager@example.com'
@@ -15,6 +18,9 @@ module Saucy
15
18
  @@layouts = Layouts.new
16
19
  @@admin_username = 'admin'
17
20
  @@admin_password = 'admin'
21
+ @@trial_length = 30
22
+ @@expiring_notice_on = 7
23
+ @@unactivated_notice_on = 7
18
24
  end
19
25
 
20
26
  end
@@ -266,6 +266,60 @@ describe Account do
266
266
  @mail.should have_received(:deliver).twice()
267
267
  end
268
268
  end
269
+
270
+ it "uses the unactivated_notice_on setting for new_unactivated" do
271
+ begin
272
+ unactivated = [Factory(:account, :created_at => 7.days.ago),
273
+ Factory(:account, :created_at => 8.days.ago)]
274
+ fresh = Factory(:account, :created_at => 6.days.ago)
275
+ Account.new_unactivated.order(:created_at).should == unactivated.reverse
276
+ Saucy::Configuration.unactivated_notice_on = 6
277
+ Account.new_unactivated.order(:created_at).should == (unactivated.reverse + [fresh]).flatten
278
+ ensure
279
+ Saucy::Configuration.unactivated_notice_on = 7
280
+ end
281
+ end
282
+
283
+ it "uses the expiring_notice_on for notifying expiring accounts" do
284
+ begin
285
+ trial = Factory(:plan, :trial => true)
286
+ forever = Factory(:plan, :trial => false)
287
+
288
+ expiring = Factory(:account, :plan => trial, :created_at => 1.day.ago)
289
+ expiring.trial_expires_at = 7.days.from_now
290
+ expiring.save!
291
+
292
+ Account.trial_expiring.should == [expiring]
293
+
294
+ Saucy::Configuration.expiring_notice_on = 8
295
+ expiring.trial_expires_at = 8.days.from_now
296
+ expiring.save!
297
+
298
+ Account.trial_expiring.should == [expiring]
299
+ ensure
300
+ Saucy::Configuration.expiring_notice_on = 7
301
+ end
302
+ end
303
+
304
+ context "with a trial length of 14 days" do
305
+ before(:each) do
306
+ Saucy::Configuration.trial_length = 14
307
+ end
308
+
309
+ after(:each) do
310
+ Saucy::Configuration.trial_length = 30
311
+ end
312
+
313
+ it "is expired with a trial plan after 14 days" do
314
+ trial = Factory(:plan, :trial => true)
315
+ Factory(:account, :created_at => 14.days.ago, :plan => trial).should be_expired
316
+ end
317
+
318
+ it "isn't expired with a trial plan before 14 days" do
319
+ trial = Factory(:plan, :trial => true)
320
+ Factory(:account, :created_at => 13.days.ago, :plan => trial).should_not be_expired
321
+ end
322
+ end
269
323
 
270
324
  it "searches records for keyword and name" do
271
325
  name = Factory :account, :name => 'match'
@@ -13,6 +13,18 @@ describe Saucy::Configuration do
13
13
  subject.support_email_address.should_not be_nil
14
14
  end
15
15
 
16
+ it "has a trial_length of 30 days" do
17
+ subject.trial_length.should == 30
18
+ end
19
+
20
+ it "has an expiring_notice_on of 7 days" do
21
+ subject.expiring_notice_on.should == 7
22
+ end
23
+
24
+ it "has an unactivated_notice_on of 7 days" do
25
+ subject.expiring_notice_on.should == 7
26
+ end
27
+
16
28
  it "has a nil merchant_account_id" do
17
29
  subject.merchant_account_id.should be_nil
18
30
  end
@@ -36,4 +48,34 @@ describe Saucy::Configuration do
36
48
  subject.support_email_address = old_address
37
49
  end
38
50
  end
51
+
52
+ it "can assign a trial length" do
53
+ old_length = subject.trial_length
54
+ begin
55
+ subject.trial_length = 14
56
+ subject.trial_length.should == 14
57
+ ensure
58
+ subject.trial_length = old_length
59
+ end
60
+ end
61
+
62
+ it "can assign an expiring_notice_on length" do
63
+ old_length = subject.expiring_notice_on
64
+ begin
65
+ subject.expiring_notice_on = 14
66
+ subject.expiring_notice_on.should == 14
67
+ ensure
68
+ subject.expiring_notice_on = old_length
69
+ end
70
+ end
71
+
72
+ it "can assign a unactivated_notice_on length" do
73
+ old_length = subject.unactivated_notice_on
74
+ begin
75
+ subject.unactivated_notice_on = 14
76
+ subject.unactivated_notice_on.should == 14
77
+ ensure
78
+ subject.unactivated_notice_on = old_length
79
+ end
80
+ end
39
81
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: saucy
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.12.1
4
5
  prerelease:
5
- version: 0.12.0
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - thoughtbot, inc.
9
9
  - Joe Ferris
10
10
  - Mike Burns
@@ -14,106 +14,103 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
-
18
- date: 2011-10-06 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
17
+ date: 2011-10-06 00:00:00.000000000Z
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
21
20
  name: clearance
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
21
+ requirement: &70295759633320 !ruby/object:Gem::Requirement
24
22
  none: false
25
- requirements:
23
+ requirements:
26
24
  - - ~>
27
- - !ruby/object:Gem::Version
25
+ - !ruby/object:Gem::Version
28
26
  version: 0.11.2
29
27
  type: :runtime
30
- version_requirements: *id001
31
- - !ruby/object:Gem::Dependency
32
- name: formtastic
33
28
  prerelease: false
34
- requirement: &id002 !ruby/object:Gem::Requirement
29
+ version_requirements: *70295759633320
30
+ - !ruby/object:Gem::Dependency
31
+ name: formtastic
32
+ requirement: &70295759632840 !ruby/object:Gem::Requirement
35
33
  none: false
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: "1.2"
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '1.2'
40
38
  type: :runtime
41
- version_requirements: *id002
42
- - !ruby/object:Gem::Dependency
43
- name: railties
44
39
  prerelease: false
45
- requirement: &id003 !ruby/object:Gem::Requirement
40
+ version_requirements: *70295759632840
41
+ - !ruby/object:Gem::Dependency
42
+ name: railties
43
+ requirement: &70295759632380 !ruby/object:Gem::Requirement
46
44
  none: false
47
- requirements:
48
- - - ">="
49
- - !ruby/object:Gem::Version
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
50
48
  version: 3.0.3
51
49
  type: :runtime
52
- version_requirements: *id003
53
- - !ruby/object:Gem::Dependency
54
- name: braintree
55
50
  prerelease: false
56
- requirement: &id004 !ruby/object:Gem::Requirement
51
+ version_requirements: *70295759632380
52
+ - !ruby/object:Gem::Dependency
53
+ name: braintree
54
+ requirement: &70295759631920 !ruby/object:Gem::Requirement
57
55
  none: false
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
61
59
  version: 2.6.2
62
60
  type: :runtime
63
- version_requirements: *id004
64
- - !ruby/object:Gem::Dependency
65
- name: sham_rack
66
61
  prerelease: false
67
- requirement: &id005 !ruby/object:Gem::Requirement
62
+ version_requirements: *70295759631920
63
+ - !ruby/object:Gem::Dependency
64
+ name: sham_rack
65
+ requirement: &70295759631460 !ruby/object:Gem::Requirement
68
66
  none: false
69
- requirements:
70
- - - "="
71
- - !ruby/object:Gem::Version
67
+ requirements:
68
+ - - =
69
+ - !ruby/object:Gem::Version
72
70
  version: 1.3.3
73
71
  type: :runtime
74
- version_requirements: *id005
75
- - !ruby/object:Gem::Dependency
76
- name: sinatra
77
72
  prerelease: false
78
- requirement: &id006 !ruby/object:Gem::Requirement
73
+ version_requirements: *70295759631460
74
+ - !ruby/object:Gem::Dependency
75
+ name: sinatra
76
+ requirement: &70295759631000 !ruby/object:Gem::Requirement
79
77
  none: false
80
- requirements:
81
- - - ">="
82
- - !ruby/object:Gem::Version
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
83
81
  version: 1.1.2
84
82
  type: :runtime
85
- version_requirements: *id006
86
- - !ruby/object:Gem::Dependency
87
- name: airbrake
88
83
  prerelease: false
89
- requirement: &id007 !ruby/object:Gem::Requirement
84
+ version_requirements: *70295759631000
85
+ - !ruby/object:Gem::Dependency
86
+ name: airbrake
87
+ requirement: &70295759630540 !ruby/object:Gem::Requirement
90
88
  none: false
91
- requirements:
89
+ requirements:
92
90
  - - ~>
93
- - !ruby/object:Gem::Version
91
+ - !ruby/object:Gem::Version
94
92
  version: 3.0.4
95
93
  type: :runtime
96
- version_requirements: *id007
97
- - !ruby/object:Gem::Dependency
98
- name: aruba
99
94
  prerelease: false
100
- requirement: &id008 !ruby/object:Gem::Requirement
95
+ version_requirements: *70295759630540
96
+ - !ruby/object:Gem::Dependency
97
+ name: aruba
98
+ requirement: &70295759630080 !ruby/object:Gem::Requirement
101
99
  none: false
102
- requirements:
103
- - - "="
104
- - !ruby/object:Gem::Version
100
+ requirements:
101
+ - - =
102
+ - !ruby/object:Gem::Version
105
103
  version: 0.2.6
106
104
  type: :development
107
- version_requirements: *id008
108
- description: Clearance-based Rails engine for Software as a Service (Saas) that provides account and project management
105
+ prerelease: false
106
+ version_requirements: *70295759630080
107
+ description: Clearance-based Rails engine for Software as a Service (Saas) that provides
108
+ account and project management
109
109
  email: support@thoughtbot.com
110
110
  executables: []
111
-
112
111
  extensions: []
113
-
114
112
  extra_rdoc_files: []
115
-
116
- files:
113
+ files:
117
114
  - CHANGELOG.md
118
115
  - Gemfile
119
116
  - Gemfile.lock
@@ -287,32 +284,29 @@ files:
287
284
  - spec/views/accounts/_account.html.erb_spec.rb
288
285
  homepage: http://github.com/thoughtbot/saucy
289
286
  licenses: []
290
-
291
287
  post_install_message:
292
288
  rdoc_options: []
293
-
294
- require_paths:
289
+ require_paths:
295
290
  - lib
296
- required_ruby_version: !ruby/object:Gem::Requirement
291
+ required_ruby_version: !ruby/object:Gem::Requirement
297
292
  none: false
298
- requirements:
299
- - - ">="
300
- - !ruby/object:Gem::Version
301
- version: "0"
302
- required_rubygems_version: !ruby/object:Gem::Requirement
293
+ requirements:
294
+ - - ! '>='
295
+ - !ruby/object:Gem::Version
296
+ version: '0'
297
+ required_rubygems_version: !ruby/object:Gem::Requirement
303
298
  none: false
304
- requirements:
305
- - - ">="
306
- - !ruby/object:Gem::Version
307
- version: "0"
299
+ requirements:
300
+ - - ! '>='
301
+ - !ruby/object:Gem::Version
302
+ version: '0'
308
303
  requirements: []
309
-
310
304
  rubyforge_project:
311
- rubygems_version: 1.8.10
305
+ rubygems_version: 1.8.6
312
306
  signing_key:
313
307
  specification_version: 3
314
308
  summary: Clearance-based Rails engine for SaaS
315
- test_files:
309
+ test_files:
316
310
  - features/run_features.feature
317
311
  - features/step_definitions/clearance_steps.rb
318
312
  - features/step_definitions/rails_steps.rb