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.
@@ -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
@@ -1,7 +1,7 @@
1
1
  class Membership < ActiveRecord::Base
2
2
  belongs_to :user
3
3
  belongs_to :account
4
- has_many :permissions, :dependent => :destroy
4
+ has_many :permissions
5
5
  has_many :projects, :through => :permissions
6
6
 
7
7
  validates_presence_of :user_id
@@ -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
@@ -203,7 +203,6 @@ module Saucy
203
203
  self.next_billing_date = result.subscription.next_billing_date
204
204
  self.subscription_status = result.subscription.status
205
205
  else
206
- p result
207
206
  false
208
207
  end
209
208
  end
@@ -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(:signup) { stub('signup', :user => user, :user= => nil, :plan= => plan) }
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 "sets the plan id in the flash" do
65
- flash[:signup_plan_id].should == plan.id
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 "sets the upgraded plan id in the flash" do
11
- flash[:upgrade_plan_id].should == account.plan_id
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).dependent(:destroy) }
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
- Saucy::Configuration.merchant_account_id = 'test'
219
- new_plan = Factory(:paid_plan, :name => "New Plan")
220
- subject.save_customer_and_subscription!(:plan_id => new_plan.id,
221
- :cardholder_name => "Ralph Robot",
222
- :billing_email => "ralph@example.com",
223
- :card_number => "4111111111111111",
224
- :verification_code => "123",
225
- :expiration_month => 5,
226
- :expiration_year => 2012)
227
-
228
- FakeBraintree.subscriptions[subject.subscription_token]["merchant_account_id"].should == 'test'
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: 69
5
- prerelease: false
4
+ hash: 15
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
- - 3
9
8
  - 4
10
- - 1
11
- version: 0.3.4.1
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-31 00:00:00 -04:00
21
+ date: 2011-03-30 00:00:00 -04:00
23
22
  default_executable:
24
23
  dependencies:
25
24
  - !ruby/object:Gem::Dependency
26
- name: formtastic
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
- - !ruby/object:Gem::Dependency
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
- - !ruby/object:Gem::Dependency
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
- - !ruby/object:Gem::Dependency
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
- - !ruby/object:Gem::Dependency
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
- - !ruby/object:Gem::Dependency
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.3.7
299
+ rubygems_version: 1.6.1
300
300
  signing_key:
301
301
  specification_version: 3
302
302
  summary: Clearance-based Rails engine for SaaS