saucy 0.3.4.1 → 0.4.0
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/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
|