saucy 0.3.4.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/app/controllers/accounts_controller.rb +4 -1
- data/app/controllers/plans_controller.rb +2 -1
- data/app/models/membership.rb +1 -1
- data/lib/saucy/configuration.rb +12 -0
- data/lib/saucy/subscription.rb +0 -1
- data/spec/controllers/accounts_controller_spec.rb +12 -3
- data/spec/controllers/plans_controller_spec.rb +2 -2
- data/spec/models/membership_spec.rb +1 -1
- data/spec/models/subscription_spec.rb +15 -11
- data/spec/saucy_spec.rb +23 -0
- data/spec/support/notifications.rb +57 -0
- metadata +25 -25
@@ -7,6 +7,8 @@ class AccountsController < ApplicationController
|
|
7
7
|
def new
|
8
8
|
@plan = Plan.find(params[:plan_id])
|
9
9
|
@signup = Signup.new
|
10
|
+
Saucy::Configuration.notify("plan_viewed", :request => request,
|
11
|
+
:plan => @plan)
|
10
12
|
end
|
11
13
|
|
12
14
|
def create
|
@@ -15,8 +17,9 @@ class AccountsController < ApplicationController
|
|
15
17
|
@signup.user = current_user
|
16
18
|
@signup.plan = @plan
|
17
19
|
if @signup.save
|
20
|
+
Saucy::Configuration.notify("account_created", :request => request,
|
21
|
+
:account => @signup.account)
|
18
22
|
flash[:success] = "Account was created."
|
19
|
-
flash[:signup_plan_id] = @plan.id
|
20
23
|
sign_in @signup.user
|
21
24
|
redirect_to root_url
|
22
25
|
else
|
@@ -13,8 +13,9 @@ class PlansController < ApplicationController
|
|
13
13
|
def update
|
14
14
|
@plans = Plan.ordered
|
15
15
|
@account = current_account
|
16
|
+
Saucy::Configuration.notify("plan_upgraded", :account => @account,
|
17
|
+
:request => request)
|
16
18
|
if @account.save_customer_and_subscription!(params[:account])
|
17
|
-
flash[:upgrade_plan_id] = @account.plan_id
|
18
19
|
redirect_to edit_account_path(@account), :notice => t('.update.notice', :default => "Plan changed successfully")
|
19
20
|
else
|
20
21
|
render :edit
|
data/app/models/membership.rb
CHANGED
data/lib/saucy/configuration.rb
CHANGED
@@ -5,10 +5,22 @@ module Saucy
|
|
5
5
|
cattr_reader :layouts
|
6
6
|
cattr_accessor :mailer_sender
|
7
7
|
cattr_accessor :merchant_account_id
|
8
|
+
cattr_accessor :observers
|
8
9
|
|
9
10
|
def initialize
|
10
11
|
@@mailer_sender = 'donotreply@example.com'
|
11
12
|
@@layouts = Layouts.new
|
13
|
+
@@observers = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.observe(observer)
|
17
|
+
@@observers << observer
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.notify(event, data)
|
21
|
+
@@observers.each do |observer|
|
22
|
+
observer.send(event, data)
|
23
|
+
end
|
12
24
|
end
|
13
25
|
end
|
14
26
|
end
|
data/lib/saucy/subscription.rb
CHANGED
@@ -29,11 +29,19 @@ describe AccountsController, "new" do
|
|
29
29
|
Signup.should have_received(:new)
|
30
30
|
should assign_to(:signup).with(signup)
|
31
31
|
end
|
32
|
+
|
33
|
+
it "notifies observers" do
|
34
|
+
should notify_observers("plan_viewed", :plan => plan, :request => request)
|
35
|
+
end
|
32
36
|
end
|
33
37
|
|
34
38
|
describe AccountsController, "successful create for a confirmed user" do
|
35
39
|
let(:user) { Factory.stub(:user) }
|
36
|
-
let(:
|
40
|
+
let(:account) { Factory.stub(:account) }
|
41
|
+
let(:signup) { stub('signup', :user => user,
|
42
|
+
:user= => nil,
|
43
|
+
:plan= => plan,
|
44
|
+
:account => account) }
|
37
45
|
let(:signup_attributes) { "attributes" }
|
38
46
|
let(:plan) { Factory(:plan) }
|
39
47
|
|
@@ -61,8 +69,9 @@ describe AccountsController, "successful create for a confirmed user" do
|
|
61
69
|
it { should_not set_the_flash.to(/confirm/i) }
|
62
70
|
it { should be_signed_in.as(user) }
|
63
71
|
|
64
|
-
it "
|
65
|
-
|
72
|
+
it "notifies observers" do
|
73
|
+
should notify_observers("account_created", :account => signup.account,
|
74
|
+
:request => request)
|
66
75
|
end
|
67
76
|
end
|
68
77
|
|
@@ -7,7 +7,7 @@ describe PlansController, "successful update", :as => :account_admin do
|
|
7
7
|
put :update, :account_id => account.to_param
|
8
8
|
end
|
9
9
|
|
10
|
-
it "
|
11
|
-
|
10
|
+
it "notifies observers" do
|
11
|
+
should notify_observers("plan_upgraded", :account => account, :request => request)
|
12
12
|
end
|
13
13
|
end
|
@@ -5,7 +5,7 @@ describe Membership do
|
|
5
5
|
it { should belong_to(:user) }
|
6
6
|
it { should validate_presence_of(:account_id) }
|
7
7
|
it { should validate_presence_of(:user_id) }
|
8
|
-
it { should have_many(:permissions)
|
8
|
+
it { should have_many(:permissions) }
|
9
9
|
it { should have_many(:projects).through(:permissions) }
|
10
10
|
|
11
11
|
describe "given an existing account membership" do
|
@@ -215,17 +215,21 @@ describe Account, "with a free plan" do
|
|
215
215
|
end
|
216
216
|
|
217
217
|
it "passes up the merchant_account_id on the subscription when it's configured" do
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
218
|
+
begin
|
219
|
+
Saucy::Configuration.merchant_account_id = 'test'
|
220
|
+
new_plan = Factory(:paid_plan, :name => "New Plan")
|
221
|
+
subject.save_customer_and_subscription!(:plan_id => new_plan.id,
|
222
|
+
:cardholder_name => "Ralph Robot",
|
223
|
+
:billing_email => "ralph@example.com",
|
224
|
+
:card_number => "4111111111111111",
|
225
|
+
:verification_code => "123",
|
226
|
+
:expiration_month => 5,
|
227
|
+
:expiration_year => 2012)
|
228
|
+
|
229
|
+
FakeBraintree.subscriptions[subject.subscription_token]["merchant_account_id"].should == 'test'
|
230
|
+
ensure
|
231
|
+
Saucy::Configuration.merchant_account_id = nil
|
232
|
+
end
|
229
233
|
end
|
230
234
|
|
231
235
|
it "doesn't create a credit card, and subscription when the plan is changed to a different free plan" do
|
data/spec/saucy_spec.rb
CHANGED
@@ -13,6 +13,23 @@ describe Saucy::Configuration do
|
|
13
13
|
subject.merchant_account_id.should be_nil
|
14
14
|
end
|
15
15
|
|
16
|
+
it "can listen for events" do
|
17
|
+
observer = stub("an observer")
|
18
|
+
cleanup_observers do
|
19
|
+
Saucy::Configuration.observe(observer)
|
20
|
+
Saucy::Configuration.observers.should include(observer)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can notify observers" do
|
25
|
+
observer = stub("an observer", :some_event => nil)
|
26
|
+
cleanup_observers do
|
27
|
+
Saucy::Configuration.observe(observer)
|
28
|
+
Saucy::Configuration.notify("some_event", "some_data")
|
29
|
+
observer.should have_received("some_event").with("some_data")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
16
33
|
it "can assign a mailer sender" do
|
17
34
|
old_sender = subject.mailer_sender
|
18
35
|
begin
|
@@ -22,4 +39,10 @@ describe Saucy::Configuration do
|
|
22
39
|
subject.mailer_sender = old_sender
|
23
40
|
end
|
24
41
|
end
|
42
|
+
|
43
|
+
def cleanup_observers
|
44
|
+
yield
|
45
|
+
ensure
|
46
|
+
subject.observers.clear
|
47
|
+
end
|
25
48
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class RecordedEvent
|
2
|
+
attr_reader :name, :data
|
3
|
+
|
4
|
+
def initialize(name, data)
|
5
|
+
@name = name.to_s
|
6
|
+
@data = data
|
7
|
+
end
|
8
|
+
|
9
|
+
def inspect
|
10
|
+
"<Event:#{name} #{inspect_data}>"
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(other)
|
14
|
+
name == other.name && data == other.data
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def inspect_data
|
20
|
+
data.inject([]) { |result, (key, value)|
|
21
|
+
result << "#{key.inspect} => #{value.inspect.slice(0, 20)}"
|
22
|
+
}.join(", ")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class RecordingObserver
|
27
|
+
attr_reader :events
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@events = []
|
31
|
+
end
|
32
|
+
|
33
|
+
def method_missing(name, data)
|
34
|
+
@events << RecordedEvent.new(name, data)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
RSpec::Matchers.define :notify_observers do |event_name, data|
|
39
|
+
match do |ignored_subject|
|
40
|
+
@event = RecordedEvent.new(event_name, data)
|
41
|
+
recorder.events.should include(@event)
|
42
|
+
end
|
43
|
+
|
44
|
+
failure_message do
|
45
|
+
"Expected event:\n#{@event.inspect}\n\nGot events:\n#{recorder.events.map(&:inspect).join("\n")}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def recorder
|
49
|
+
Saucy::Configuration.observers.last
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
RSpec.configure do |config|
|
54
|
+
config.before do
|
55
|
+
Saucy::Configuration.observers = [RecordingObserver.new]
|
56
|
+
end
|
57
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saucy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 15
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
- 3
|
9
8
|
- 4
|
10
|
-
-
|
11
|
-
version: 0.
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
12
11
|
platform: ruby
|
13
12
|
authors:
|
14
13
|
- thoughtbot, inc.
|
@@ -19,12 +18,11 @@ autorequire:
|
|
19
18
|
bindir: bin
|
20
19
|
cert_chain: []
|
21
20
|
|
22
|
-
date: 2011-03-
|
21
|
+
date: 2011-03-30 00:00:00 -04:00
|
23
22
|
default_executable:
|
24
23
|
dependencies:
|
25
24
|
- !ruby/object:Gem::Dependency
|
26
|
-
|
27
|
-
prerelease: false
|
25
|
+
type: :runtime
|
28
26
|
requirement: &id001 !ruby/object:Gem::Requirement
|
29
27
|
none: false
|
30
28
|
requirements:
|
@@ -35,11 +33,11 @@ dependencies:
|
|
35
33
|
- 1
|
36
34
|
- 2
|
37
35
|
version: "1.2"
|
38
|
-
type: :runtime
|
39
36
|
version_requirements: *id001
|
40
|
-
|
41
|
-
name: railties
|
37
|
+
name: formtastic
|
42
38
|
prerelease: false
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
type: :runtime
|
43
41
|
requirement: &id002 !ruby/object:Gem::Requirement
|
44
42
|
none: false
|
45
43
|
requirements:
|
@@ -51,11 +49,11 @@ dependencies:
|
|
51
49
|
- 0
|
52
50
|
- 3
|
53
51
|
version: 3.0.3
|
54
|
-
type: :runtime
|
55
52
|
version_requirements: *id002
|
56
|
-
|
57
|
-
name: braintree
|
53
|
+
name: railties
|
58
54
|
prerelease: false
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
type: :runtime
|
59
57
|
requirement: &id003 !ruby/object:Gem::Requirement
|
60
58
|
none: false
|
61
59
|
requirements:
|
@@ -67,11 +65,11 @@ dependencies:
|
|
67
65
|
- 6
|
68
66
|
- 2
|
69
67
|
version: 2.6.2
|
70
|
-
type: :runtime
|
71
68
|
version_requirements: *id003
|
72
|
-
|
73
|
-
name: sham_rack
|
69
|
+
name: braintree
|
74
70
|
prerelease: false
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
type: :runtime
|
75
73
|
requirement: &id004 !ruby/object:Gem::Requirement
|
76
74
|
none: false
|
77
75
|
requirements:
|
@@ -83,11 +81,11 @@ dependencies:
|
|
83
81
|
- 3
|
84
82
|
- 3
|
85
83
|
version: 1.3.3
|
86
|
-
type: :runtime
|
87
84
|
version_requirements: *id004
|
88
|
-
|
89
|
-
name: sinatra
|
85
|
+
name: sham_rack
|
90
86
|
prerelease: false
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
type: :runtime
|
91
89
|
requirement: &id005 !ruby/object:Gem::Requirement
|
92
90
|
none: false
|
93
91
|
requirements:
|
@@ -99,11 +97,11 @@ dependencies:
|
|
99
97
|
- 1
|
100
98
|
- 2
|
101
99
|
version: 1.1.2
|
102
|
-
type: :runtime
|
103
100
|
version_requirements: *id005
|
104
|
-
|
105
|
-
name: aruba
|
101
|
+
name: sinatra
|
106
102
|
prerelease: false
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
type: :development
|
107
105
|
requirement: &id006 !ruby/object:Gem::Requirement
|
108
106
|
none: false
|
109
107
|
requirements:
|
@@ -115,8 +113,9 @@ dependencies:
|
|
115
113
|
- 2
|
116
114
|
- 6
|
117
115
|
version: 0.2.6
|
118
|
-
type: :development
|
119
116
|
version_requirements: *id006
|
117
|
+
name: aruba
|
118
|
+
prerelease: false
|
120
119
|
description: Clearance-based Rails engine for Software as a Service (Saas) that provides account and project management
|
121
120
|
email: support@thoughtbot.com
|
122
121
|
executables: []
|
@@ -265,6 +264,7 @@ files:
|
|
265
264
|
- spec/support/authorization_helpers.rb
|
266
265
|
- spec/support/braintree.rb
|
267
266
|
- spec/support/clearance_matchers.rb
|
267
|
+
- spec/support/notifications.rb
|
268
268
|
- spec/views/accounts/_account.html.erb_spec.rb
|
269
269
|
has_rdoc: true
|
270
270
|
homepage: http://github.com/thoughtbot/saucy
|
@@ -296,7 +296,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
296
296
|
requirements: []
|
297
297
|
|
298
298
|
rubyforge_project:
|
299
|
-
rubygems_version: 1.
|
299
|
+
rubygems_version: 1.6.1
|
300
300
|
signing_key:
|
301
301
|
specification_version: 3
|
302
302
|
summary: Clearance-based Rails engine for SaaS
|