saucy 0.12.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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