acts_as_subscription 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,207 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe Subscription do
4
+
5
+ before(:each) do
6
+ @free_attr = free_attributes
7
+ @paid_attr = paid_attributes
8
+ end
9
+
10
+ describe 'initialization' do
11
+
12
+ it 'should initialize the backend' do
13
+ subscription = model_factory
14
+ ActsAsSubscription::Subscription::Backend.config.should_not == nil
15
+ ActsAsSubscription::Subscription::Backend.instance.class.should == ActsAsSubscription::Subscription::Backend::DummyClient
16
+ end
17
+
18
+ it 'should create the customer code automatically' do
19
+ subscription = Subscription.new(@free_attr)
20
+ subscription.customer_code.should_not == nil
21
+ end
22
+
23
+ it 'should create a CreditCard instance' do
24
+ subscription = Subscription.new(@free_attr)
25
+ subscription.credit_card.class.should == ActiveMerchant::Billing::CreditCard
26
+ end
27
+
28
+ end
29
+
30
+ describe 'validation' do
31
+
32
+ describe 'for all plans' do
33
+
34
+ it 'should require an email' do
35
+ subscription = Subscription.new(@free_attr.merge(:email => ''))
36
+ subscription.should_not be_valid
37
+ end
38
+
39
+ it 'should require a first_name' do
40
+ subscription = Subscription.new(@free_attr.merge(:first_name => ''))
41
+ subscription.should_not be_valid
42
+ end
43
+
44
+ it 'should require a last_name' do
45
+ subscription = Subscription.new(@free_attr.merge(:last_name => ''))
46
+ subscription.should_not be_valid
47
+ end
48
+
49
+ it 'should require a customer_code' do
50
+ subscription = Subscription.new(@free_attr.merge(:customer_code => ''))
51
+ subscription.should_not be_valid
52
+ end
53
+
54
+ it 'is_free_plan? should return false if the :plan_code is missing' do
55
+ subscription = Subscription.new(@free_attr.merge(:plan_code => nil))
56
+ subscription.is_free_plan?.should == false
57
+ subscription = Subscription.new(@free_attr.merge(:plan_code => ''))
58
+ subscription.is_free_plan?.should == false
59
+ subscription = Subscription.new(@free_attr.merge(:plan_code => ' '))
60
+ subscription.is_free_plan?.should == false
61
+ end
62
+
63
+ it 'is_free_plan? should return true if the :plan_code contains the string "free"' do
64
+ subscription = Subscription.new(@free_attr.merge(:plan_code => 'free_plan'))
65
+ subscription.is_free_plan?.should == true
66
+ subscription = Subscription.new(@free_attr.merge(:plan_code => 'plan_free_plan'))
67
+ subscription.is_free_plan?.should == true
68
+ subscription = Subscription.new(@free_attr.merge(:plan_code => 'free'))
69
+ subscription.is_free_plan?.should == true
70
+ subscription = Subscription.new(@free_attr.merge(:plan_code => 'FREE'))
71
+ subscription.is_free_plan?.should == true
72
+ subscription = Subscription.new(@free_attr.merge(:plan_code => 'MY_PLAN (frEe)'))
73
+ subscription.is_free_plan?.should == true
74
+ end
75
+
76
+ end
77
+
78
+ describe 'for free plans' do
79
+
80
+ describe 'with valid parameters' do
81
+
82
+ it 'should validate' do
83
+ subscription = Subscription.new(@free_attr)
84
+ subscription.should be_valid
85
+ end
86
+
87
+ it 'should create a new record on save' do
88
+ lambda do
89
+ Subscription.create(@free_attr)
90
+ end.should change(Subscription, :count).by(1)
91
+ end
92
+
93
+ it 'should identify as a free plan' do
94
+ subscription = Subscription.new(@free_attr)
95
+ subscription.is_free_plan?.should == true
96
+ end
97
+
98
+ end
99
+
100
+ describe 'with invalid parameters' do
101
+
102
+ it 'should be invalid' do
103
+ subscription = Subscription.new(@free_attr.merge(:first_name => ''))
104
+ subscription.should_not be_valid
105
+ end
106
+
107
+ it 'should not create a new record on save' do
108
+ lambda do
109
+ Subscription.create(@free_attr.merge(:first_name => ''))
110
+ end.should_not change(Subscription, :count)
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+
117
+ describe 'for paid plans' do
118
+
119
+ it 'should require a zip_code' do
120
+ subscription = Subscription.new(@paid_attr.merge(:zip_code => ''))
121
+ subscription.should_not be_valid
122
+ end
123
+
124
+ it 'should require a cc_expiration_month' do
125
+ subscription = Subscription.new(@paid_attr.merge(:cc_expiration_month => ''))
126
+ subscription.should_not be_valid
127
+ end
128
+
129
+ it 'should require a cc_expiration_year' do
130
+ subscription = Subscription.new(@paid_attr.merge(:cc_expiration_year => ''))
131
+ subscription.should_not be_valid
132
+ end
133
+
134
+ it 'should require a cc_verification_value' do
135
+ subscription = Subscription.new(@paid_attr.merge(:cc_verification_value => ''))
136
+ subscription.should_not be_valid
137
+ end
138
+
139
+ it 'should require a cc_number' do
140
+ subscription = Subscription.new(@paid_attr.merge(:cc_number => ''))
141
+ subscription.should_not be_valid
142
+ end
143
+
144
+ describe 'with valid parameters' do
145
+
146
+ it 'should validate' do
147
+ subscription = Subscription.new(@paid_attr)
148
+ subscription.should be_valid
149
+ end
150
+
151
+ it 'should create a new record on save' do
152
+ lambda do
153
+ Subscription.create(@paid_attr)
154
+ end.should change(Subscription, :count).by(1)
155
+ end
156
+
157
+ it 'should set cc_last_digits on validation' do
158
+ subscription = Subscription.new(@paid_attr)
159
+ subscription.valid?
160
+ subscription.cc_last_digits.should == @paid_attr[:cc_number].reverse[0, 4].reverse
161
+ end
162
+
163
+ it 'should identify as a paid plan' do
164
+ subscription = Subscription.new(@paid_attr)
165
+ subscription.is_free_plan?.should == false
166
+ end
167
+
168
+ it 'should update the internal CreditCard instance on validate' do
169
+ subscription = Subscription.new(@paid_attr)
170
+ subscription.credit_card.first_name.should == nil
171
+ subscription.credit_card.first_name.should == nil
172
+ subscription.credit_card.last_name.should == nil
173
+ subscription.credit_card.month.should == nil
174
+ subscription.credit_card.year.should == nil
175
+ subscription.credit_card.verification_value.should == nil
176
+ subscription.credit_card.number.should == nil
177
+ subscription.valid?
178
+ subscription.credit_card.first_name.should == @paid_attr[:first_name]
179
+ subscription.credit_card.last_name.should == @paid_attr[:last_name]
180
+ subscription.credit_card.month.should == @paid_attr[:cc_expiration_month]
181
+ subscription.credit_card.year.should == @paid_attr[:cc_expiration_year]
182
+ subscription.credit_card.verification_value.should == @paid_attr[:cc_verification_value]
183
+ subscription.credit_card.number.should == @paid_attr[:cc_number]
184
+ end
185
+
186
+ end
187
+
188
+ describe 'with invalid parameters' do
189
+
190
+ it 'should be invalid' do
191
+ subscription = Subscription.new(@paid_attr.merge(:first_name => ''))
192
+ subscription.should_not be_valid
193
+ end
194
+
195
+ it 'should not create a new record on save' do
196
+ lambda do
197
+ Subscription.create(@paid_attr.merge(:first_name => ''))
198
+ end.should_not change(Subscription, :count)
199
+ end
200
+
201
+ end
202
+
203
+ end
204
+
205
+ end # validation
206
+
207
+ end
@@ -0,0 +1,110 @@
1
+ $LOAD_PATH << "." unless $LOAD_PATH.include?(".")
2
+
3
+ begin
4
+ require 'active_record'
5
+ require 'bundler'
6
+ require 'rubygems'
7
+
8
+ if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new('0.9.5')
9
+ raise RuntimeError, "Your bundler version is too old." +
10
+ "Run `gem install bundler` to upgrade."
11
+ end
12
+
13
+ # Set up load paths for all bundled gems
14
+ Bundler.setup
15
+ rescue Bundler::GemNotFound
16
+ raise RuntimeError, "Bundler couldn't find some gems." +
17
+ "Did you run `bundle install`?"
18
+ end
19
+
20
+ Bundler.require
21
+ require File.expand_path('../../lib/acts_as_subscription', __FILE__)
22
+
23
+ ENV['DB'] ||= 'sqlite3'
24
+
25
+ database_yml = File.expand_path('../support/database.yml', __FILE__)
26
+ if File.exists?(database_yml)
27
+ active_record_configuration = YAML.load_file(database_yml)[ENV['DB']]
28
+
29
+ ActiveRecord::Base.establish_connection(active_record_configuration)
30
+ ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
31
+
32
+ ActiveRecord::Base.silence do
33
+ ActiveRecord::Migration.verbose = false
34
+
35
+ load(File.dirname(__FILE__) + '/support/schema.rb')
36
+ load(File.dirname(__FILE__) + '/support/models.rb')
37
+ end
38
+
39
+ else
40
+ raise "Please create #{database_yml} first to configure your database. Take a look at: #{database_yml}.example"
41
+ end
42
+
43
+ def backend_config(backend_name)
44
+ backend_yml = File.expand_path('../support/backend.yml', __FILE__)
45
+ if File.exists?(backend_yml)
46
+ config = YAML.load_file(backend_yml)
47
+
48
+ # Check that config is defined for this backend.
49
+ unless config[backend_name.to_s]
50
+ raise "Please create a section for '#{backend_name}' in #{backend_yml}"
51
+ end
52
+
53
+ config[backend_name.to_s]
54
+ else
55
+ raise "Please create #{backend_yml} first to configure backend authentication. Take a look at: #{backend_yml}.example"
56
+ end
57
+ end
58
+
59
+ def free_attributes
60
+ {
61
+ :email => 'dummy@recursive-design.com',
62
+ :plan_code => 'FREE',
63
+ :customer_code => UUIDTools::UUID.random_create.to_s,
64
+ :first_name => 'Testy',
65
+ :last_name => 'McTest',
66
+ }
67
+ end
68
+
69
+ def paid_attributes
70
+ {
71
+ :email => 'dummy@recursive-design.com',
72
+ :plan_code => 'PRO',
73
+ :customer_code => UUIDTools::UUID.random_create.to_s,
74
+ :first_name => 'Testy',
75
+ :last_name => 'McTest',
76
+ :cc_expiration_month => 1,
77
+ :cc_expiration_year => 2012,
78
+ :cc_number => '4111111111111111',
79
+ :cc_verification_value => '123',
80
+ :zip_code => '90210',
81
+ }
82
+ end
83
+
84
+ def model_factory(params={})
85
+ defaults = {:backend => :dummy, :user => 'user', :pass => 'pass'}
86
+ params = defaults.merge(params)
87
+ param_str = params.collect { |name, value|
88
+ if (value.class == Symbol)
89
+ value = ":#{value}"
90
+ else
91
+ value = "'#{value}'"
92
+ end
93
+ ":#{name} => #{value}" }.join(', ')
94
+ klass = eval <<-RUBY_EVAL
95
+ class Subscription < ActiveRecord::Base
96
+ include ActsAsSubscription::Subscription
97
+ acts_as_subscription #{param_str}
98
+ end
99
+ RUBY_EVAL
100
+ klass
101
+ end
102
+
103
+ def clean_database!
104
+ models = [Subscription]
105
+ models.each do |model|
106
+ ActiveRecord::Base.connection.execute "DELETE FROM #{model.table_name}"
107
+ end
108
+ end
109
+
110
+ clean_database!
@@ -0,0 +1,14 @@
1
+ cheddar_getter:
2
+ user: 'user@test.com'
3
+ pass: 'pass'
4
+ product_code: 'my_product'
5
+
6
+ recurly:
7
+ user: 'user@test.com'
8
+ pass: 'pass'
9
+ product_code: 'my_product'
10
+
11
+ chargify:
12
+ user: 'user@test.com'
13
+ pass: 'pass'
14
+ product_code: 'my_product'
@@ -0,0 +1,17 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: acts_as_subscription.sqlite3
4
+
5
+ mysql:
6
+ adapter: mysql
7
+ hostname: localhost
8
+ username: root
9
+ password:
10
+ database: acts_as_subscription
11
+
12
+ postgresql:
13
+ adapter: postgresql
14
+ hostname: localhost
15
+ username: postgres
16
+ password:
17
+ database: acts_as_subscription
@@ -0,0 +1,21 @@
1
+
2
+ class Subscription < ActiveRecord::Base
3
+
4
+ # Doesn't work without this include for gem testing - not needed for real-world use.
5
+ include ActsAsSubscription::Subscription
6
+
7
+ acts_as_subscription :backend => :dummy,
8
+ :user => 'user',
9
+ :password => 'pass',
10
+ :product_code => 'DUMMY_TEST'
11
+
12
+ end
13
+
14
+
15
+ class SubscriptionPlan < ActiveRecord::Base
16
+
17
+ include ActsAsSubscription::SubscriptionPlan
18
+
19
+ acts_as_subscription_plan
20
+
21
+ end
@@ -0,0 +1,30 @@
1
+
2
+ ActiveRecord::Schema.define :version => 0 do
3
+
4
+ create_table :subscriptions, :force => true do |t|
5
+ t.string :customer_code, :null => false
6
+ t.string :email, :null => false
7
+ t.string :first_name, :null => false
8
+ t.string :last_name, :null => false
9
+ t.string :plan_code, :null => false
10
+ t.string :zip_code
11
+ t.integer :cc_expiration_month
12
+ t.integer :cc_expiration_year
13
+ t.string :cc_last_digits
14
+ t.string :cc_verification_value
15
+ t.datetime :canceled_at
16
+ t.datetime :suspended_at
17
+ t.timestamps
18
+ end
19
+
20
+ create_table :subscription_plans, :force => true do |t|
21
+ t.string :code, :null => false
22
+ t.string :name, :null => false
23
+ t.text :description
24
+ t.string :billing_frequency, :null => false
25
+ t.float :recurring_charge, :null => false
26
+ t.boolean :active, :default => true
27
+ t.timestamps
28
+ end
29
+
30
+ end
metadata ADDED
@@ -0,0 +1,244 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: acts_as_subscription
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Dave Perrett
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-01 00:00:00 +10:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ type: :runtime
23
+ prerelease: false
24
+ name: activemerchant
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ hash: 53
31
+ segments:
32
+ - 1
33
+ - 9
34
+ - 3
35
+ version: 1.9.3
36
+ requirement: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ type: :runtime
39
+ prerelease: false
40
+ name: chargify_api_ares
41
+ version_requirements: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ hash: 29
47
+ segments:
48
+ - 0
49
+ - 3
50
+ - 7
51
+ version: 0.3.7
52
+ requirement: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ type: :runtime
55
+ prerelease: false
56
+ name: hpricot
57
+ version_requirements: &id003 !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 7
63
+ segments:
64
+ - 0
65
+ - 6
66
+ version: "0.6"
67
+ requirement: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ type: :runtime
70
+ prerelease: false
71
+ name: mousetrap
72
+ version_requirements: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ hash: 11
78
+ segments:
79
+ - 0
80
+ - 5
81
+ - 0
82
+ version: 0.5.0
83
+ requirement: *id004
84
+ - !ruby/object:Gem::Dependency
85
+ type: :runtime
86
+ prerelease: false
87
+ name: rails
88
+ version_requirements: &id005 !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ hash: 1
94
+ segments:
95
+ - 3
96
+ - 0
97
+ - 3
98
+ version: 3.0.3
99
+ requirement: *id005
100
+ - !ruby/object:Gem::Dependency
101
+ type: :runtime
102
+ prerelease: false
103
+ name: uuidtools
104
+ version_requirements: &id006 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ hash: 3
110
+ segments:
111
+ - 0
112
+ version: "0"
113
+ requirement: *id006
114
+ - !ruby/object:Gem::Dependency
115
+ type: :development
116
+ prerelease: false
117
+ name: bundler
118
+ version_requirements: &id007 !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ~>
122
+ - !ruby/object:Gem::Version
123
+ hash: 23
124
+ segments:
125
+ - 1
126
+ - 0
127
+ - 0
128
+ version: 1.0.0
129
+ requirement: *id007
130
+ - !ruby/object:Gem::Dependency
131
+ type: :development
132
+ prerelease: false
133
+ name: jeweler
134
+ version_requirements: &id008 !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ~>
138
+ - !ruby/object:Gem::Version
139
+ hash: 7
140
+ segments:
141
+ - 1
142
+ - 5
143
+ - 2
144
+ version: 1.5.2
145
+ requirement: *id008
146
+ - !ruby/object:Gem::Dependency
147
+ type: :development
148
+ prerelease: false
149
+ name: rcov
150
+ version_requirements: &id009 !ruby/object:Gem::Requirement
151
+ none: false
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ hash: 41
156
+ segments:
157
+ - 0
158
+ - 9
159
+ - 9
160
+ version: 0.9.9
161
+ requirement: *id009
162
+ description: With ActsAsSubscription, you can hook your model into several subscription services, such as CheddarGetter.
163
+ email: mail@recursive-design.com
164
+ executables: []
165
+
166
+ extensions: []
167
+
168
+ extra_rdoc_files:
169
+ - LICENSE.txt
170
+ - README.rdoc
171
+ files:
172
+ - .autotest
173
+ - .rspec
174
+ - .rvmrc
175
+ - Gemfile
176
+ - LICENSE.txt
177
+ - README.rdoc
178
+ - Rakefile
179
+ - VERSION
180
+ - acts_as_subscription.gemspec
181
+ - autotest/discover.rb
182
+ - lib/acts_as_subscription.rb
183
+ - lib/acts_as_subscription/backend.rb
184
+ - lib/acts_as_subscription/backend/chargify_client.rb
185
+ - lib/acts_as_subscription/backend/cheddar_getter_client.rb
186
+ - lib/acts_as_subscription/backend/dummy_client.rb
187
+ - lib/acts_as_subscription/backend/recurly_client.rb
188
+ - lib/acts_as_subscription/error.rb
189
+ - lib/acts_as_subscription/railtie.rb
190
+ - lib/acts_as_subscription/subscription.rb
191
+ - lib/acts_as_subscription/subscription_plan.rb
192
+ - spec/backend/backend/chargify_client_spec.rb
193
+ - spec/backend/backend/cheddar_getter_client_spec.rb
194
+ - spec/backend/backend_spec.rb
195
+ - spec/models/subscription_plan_spec.rb
196
+ - spec/models/subscription_spec.rb
197
+ - spec/spec_helper.rb
198
+ - spec/support/backend.yml.example
199
+ - spec/support/database.yml
200
+ - spec/support/models.rb
201
+ - spec/support/schema.rb
202
+ has_rdoc: true
203
+ homepage: http://recursive-design.com/
204
+ licenses: []
205
+
206
+ post_install_message:
207
+ rdoc_options: []
208
+
209
+ require_paths:
210
+ - lib
211
+ required_ruby_version: !ruby/object:Gem::Requirement
212
+ none: false
213
+ requirements:
214
+ - - ">="
215
+ - !ruby/object:Gem::Version
216
+ hash: 3
217
+ segments:
218
+ - 0
219
+ version: "0"
220
+ required_rubygems_version: !ruby/object:Gem::Requirement
221
+ none: false
222
+ requirements:
223
+ - - ">="
224
+ - !ruby/object:Gem::Version
225
+ hash: 3
226
+ segments:
227
+ - 0
228
+ version: "0"
229
+ requirements: []
230
+
231
+ rubyforge_project: nowarning
232
+ rubygems_version: 1.3.7
233
+ signing_key:
234
+ specification_version: 3
235
+ summary: ActsAsSubscription is a plugin for rails that provides recurring subscription capabilities to a model.
236
+ test_files:
237
+ - spec/backend/backend/chargify_client_spec.rb
238
+ - spec/backend/backend/cheddar_getter_client_spec.rb
239
+ - spec/backend/backend_spec.rb
240
+ - spec/models/subscription_plan_spec.rb
241
+ - spec/models/subscription_spec.rb
242
+ - spec/spec_helper.rb
243
+ - spec/support/models.rb
244
+ - spec/support/schema.rb