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.
@@ -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