acts_as_tenant 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ae0af3ec60e0f5aec616181f0cb84dbf819838d5
4
- data.tar.gz: 24f836a129e42dbe7bf60aff0eb5cf3942eabc4d
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTdlZmJkZjFiNWQ5YzUxNDM0OWJiOWEzYWMzZTIzZWM3ZmMzN2RmOA==
5
+ data.tar.gz: !binary |-
6
+ NTViNTg4MDVkYjIwYmY4Y2VlZWY0NGVkNmE2MzEzNjk2ODE5YjEwOA==
5
7
  SHA512:
6
- metadata.gz: d5946028e86ba16bde4ed1ad232b2f89d75302111e44bcb765e144688e16f21c697d1951fae80160e5263c96c43871380e007a2ef813631278c932b2896f7e2c
7
- data.tar.gz: 2a2f574538b2507d3837b1d6d3919acf409df8599afded9127c7d991baac5ba40f85e77f135ae1655bacce560ffe14672b462a43b909958c059ede1e17f4ca0a
8
+ metadata.gz: !binary |-
9
+ MzZlMWJmNzAyZGQ2NDUwYWFmYjIzN2Q3YjliZDhlMjA4NGVjNzcwMGE4Yzc1
10
+ MzRmOGZmNTE0Yzk3NTY3YTI5ZTU2ZTBhNDczYTlmZjU0Y2JjYWY1MDM5ODE5
11
+ NTNhODA2ZjczYzk4Y2VkZjg4MDhmYTNlMDc5Y2UzZjgyNzBmZDA=
12
+ data.tar.gz: !binary |-
13
+ MjM2NzliNjViYjlkNjQyNjdmODNiMWY2MGFkODQ1ZjJiODQ1YjRjMzJkOWM2
14
+ MGFjNjJkNWVhNDkxMTE1NGZmZGIwZDM2ODA0ZWE3MmM0ZDQxMGNmYTcwMTVh
15
+ YzM3OWU5ZjUyYTJmZmExYTEyMDFiY2YyZmIzZThhYzhlMGYxNzI=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ 0.3.2
2
+ -----
3
+ * correctly support nested models with has_many :through (thx dexion)
4
+ * Support 'www.subdomain.example.com' (thx wtfiwtz)
5
+ * Support setting `tenant_id` on scoped models if the `tenant_id` is nil (thx Matt Wilson)
6
+
1
7
  0.3.1
2
8
  -----
3
9
  * Added support for Rails 4
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  Acts As Tenant
2
2
  ==============
3
3
 
4
+ [![Build Status](https://travis-ci.org/ErwinM/acts_as_tenant.png)](https://travis-ci.org/ErwinM/acts_as_tenant)
5
+
4
6
  **Note**: acts_as_tenant was introduced in this [blog post](http://www.rollcallapp.com/blog/2011/10/03/adding-multi-tenancy-to-your-rails-app-acts-as-tenant).
5
7
 
6
8
  This gem was born out of our own need for a fail-safe and out-of-the-way manner to add multi-tenancy to our Rails app through a shared database strategy, that integrates (near) seamless with Rails.
data/Rakefile CHANGED
@@ -1 +1,5 @@
1
1
  require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task :default => :spec
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
24
24
  #s.add_dependency('request_store', '>= 1.0.5')
25
25
 
26
26
  s.add_development_dependency('rspec')
27
+ s.add_development_dependency('rspec-rails')
27
28
  s.add_development_dependency('database_cleaner')
28
29
  s.add_development_dependency('sqlite3')
29
30
  s.add_development_dependency('debugger')
@@ -18,7 +18,7 @@ module ActsAsTenant
18
18
 
19
19
  private
20
20
  def find_tenant_by_subdomain
21
- ActsAsTenant.current_tenant = tenant_class.where(tenant_column => request.subdomains.first).first
21
+ ActsAsTenant.current_tenant = tenant_class.where(tenant_column => request.subdomains.last).first
22
22
  end
23
23
 
24
24
  def current_tenant
@@ -29,8 +29,10 @@ module ActsAsTenant
29
29
  old_tenant = self.current_tenant
30
30
  self.current_tenant = tenant
31
31
  value = block.call
32
- self.current_tenant = old_tenant
33
32
  return value
33
+
34
+ ensure
35
+ self.current_tenant = old_tenant
34
36
  end
35
37
 
36
38
  module ModelExtensions
@@ -47,7 +49,7 @@ module ActsAsTenant
47
49
  if ActsAsTenant.configuration.require_tenant && ActsAsTenant.current_tenant.nil?
48
50
  raise ActsAsTenant::Errors::NoTenantSet
49
51
  end
50
- where({ActsAsTenant.fkey => ActsAsTenant.current_tenant.id}) if ActsAsTenant.current_tenant
52
+ where("#{self.table_name}.#{ActsAsTenant.fkey} = ?", ActsAsTenant.current_tenant.id) if ActsAsTenant.current_tenant
51
53
  }
52
54
 
53
55
  # Add the following validations to the receiving model:
@@ -74,13 +76,13 @@ module ActsAsTenant
74
76
  # - Add a helper method to verify if a model has been scoped by AaT
75
77
  #
76
78
  define_method "#{ActsAsTenant.fkey}=" do |integer|
77
- raise ActsAsTenant::Errors::TenantIsImmutable unless new_record?
78
- write_attribute("#{ActsAsTenant.fkey}", integer)
79
+ raise ActsAsTenant::Errors::TenantIsImmutable unless new_record? || send(ActsAsTenant.fkey).nil?
80
+ write_attribute("#{ActsAsTenant.fkey}", integer)
79
81
  end
80
82
 
81
- define_method "#{ActsAsTenant.tenant_klass.to_s}=" do |model|
82
- raise ActsAsTenant::Errors::TenantIsImmutable unless new_record?
83
- super(model)
83
+ define_method "#{ActsAsTenant.tenant_klass.to_s}=" do |model|
84
+ raise ActsAsTenant::Errors::TenantIsImmutable unless new_record? || send(ActsAsTenant.fkey).nil?
85
+ super(model)
84
86
  end
85
87
 
86
88
  def scoped_by_tenant?
@@ -1,3 +1,3 @@
1
1
  module ActsAsTenant
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -4,6 +4,7 @@ require 'spec_helper'
4
4
  ActiveRecord::Schema.define(:version => 1) do
5
5
  create_table :accounts, :force => true do |t|
6
6
  t.column :name, :string
7
+ t.column :subdomain, :string
7
8
  end
8
9
 
9
10
  create_table :projects, :force => true do |t|
@@ -165,7 +166,7 @@ describe ActsAsTenant do
165
166
  end
166
167
  end
167
168
 
168
- describe 'tenant_id should be immutable' do
169
+ describe 'tenant_id should be immutable, if already set' do
169
170
  before do
170
171
  @account = Account.create!(:name => 'foo')
171
172
  @project = @account.projects.create!(:name => 'bar')
@@ -174,6 +175,16 @@ describe ActsAsTenant do
174
175
  it { lambda {@project.account_id = @account.id + 1}.should raise_error }
175
176
  end
176
177
 
178
+ describe 'tenant_id should be mutable, if not already set' do
179
+ before do
180
+ @account = Account.create!(:name => 'foo')
181
+ @project = Project.create!(:name => 'bar')
182
+ end
183
+
184
+ it { @project.account_id.should be_nil }
185
+ it { lambda { @project.account = @account }.should_not raise_error }
186
+ end
187
+
177
188
  describe 'Associations can only be made with in-scope objects' do
178
189
  before do
179
190
  @account = Account.create!(:name => 'foo')
@@ -275,7 +286,7 @@ describe ActsAsTenant do
275
286
  @project1 = @account1.projects.create!(:name => 'foobar')
276
287
  ActsAsTenant.configuration.stub(require_tenant: true)
277
288
  end
278
-
289
+
279
290
  it "should raise an error when no tenant is provided" do
280
291
  expect { Project.all.load }.to raise_error(ActsAsTenant::Errors::NoTenantSet)
281
292
  end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+
3
+ #Setup test specific ApplicationController
4
+ class Account
5
+ attr_accessor :name
6
+ end
7
+
8
+ class ApplicationController2 < ActionController::Base
9
+ include Rails.application.routes.url_helpers
10
+ set_current_tenant_through_filter
11
+ before_filter :your_method_that_finds_the_current_tenant
12
+
13
+ def your_method_that_finds_the_current_tenant
14
+ current_account = Account.new
15
+ current_account.name = 'account1'
16
+ set_current_tenant(current_account)
17
+ end
18
+
19
+ end
20
+
21
+ # Start testing
22
+ describe ApplicationController2, :type => :controller do
23
+ controller do
24
+ def index
25
+ render :text => "custom called"
26
+ end
27
+ end
28
+
29
+ it 'Finds the correct tenant using the filter command' do
30
+ get :index
31
+ ActsAsTenant.current_tenant.name.should eq 'account1'
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ require "spec_helper"
2
+
3
+ #Setup test specific ApplicationController
4
+ class Account; end # this is so the spec will work in isolation
5
+
6
+ class ApplicationController < ActionController::Base
7
+ include Rails.application.routes.url_helpers
8
+ set_current_tenant_by_subdomain
9
+ end
10
+
11
+ # Start testing
12
+ describe ApplicationController, :type => :controller do
13
+ controller do
14
+ def index
15
+ render :text => "custom called"
16
+ end
17
+ end
18
+
19
+ it 'Finds the correct tenant with a subdomain.example.com' do
20
+ @request.host = "account1.example.com"
21
+ Account.should_receive(:where).with({subdomain: 'account1'}) {['account1']}
22
+ get :index
23
+ ActsAsTenant.current_tenant.should eq 'account1'
24
+ end
25
+
26
+ it 'Finds the correct tenant with a www.subdomain.example.com' do
27
+ @request.host = "www.account1.example.com"
28
+ Account.should_receive(:where).with({subdomain: 'account1'}) {['account1']}
29
+ get :index
30
+ ActsAsTenant.current_tenant.should eq 'account1'
31
+ end
32
+ end
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,8 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
3
 
4
4
  require 'database_cleaner'
5
5
  require 'acts_as_tenant'
6
+ require 'rspec/rails'
7
+ require 'rails'
6
8
 
7
9
  config = YAML::load(IO.read(File.join(File.dirname(__FILE__), 'database.yml')))
8
10
  ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
@@ -22,5 +24,14 @@ RSpec.configure do |config|
22
24
  DatabaseCleaner.clean
23
25
  ActsAsTenant.current_tenant = nil
24
26
  end
27
+
28
+ config.infer_base_class_for_anonymous_controllers = true
29
+ end
25
30
 
26
- end
31
+ # Setup a test app
32
+ module Rollcall
33
+ class Application < Rails::Application; end
34
+ end
35
+
36
+ Rollcall::Application.config.secret_token = '1234567890123456789012345678901234567890'
37
+ Rollcall::Application.config.secret_key_base = '1234567890123456789012345678901234567890'
metadata CHANGED
@@ -1,97 +1,111 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_tenant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erwin Matthijssen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-24 00:00:00.000000000 Z
11
+ date: 2014-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: request_store
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 1.0.5
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.0.5
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ! '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '3.1'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ! '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: database_cleaner
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - '>='
73
+ - - ! '>='
60
74
  - !ruby/object:Gem::Version
61
75
  version: '0'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - '>='
80
+ - - ! '>='
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: sqlite3
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - '>='
87
+ - - ! '>='
74
88
  - !ruby/object:Gem::Version
75
89
  version: '0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - '>='
94
+ - - ! '>='
81
95
  - !ruby/object:Gem::Version
82
96
  version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: debugger
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - '>='
101
+ - - ! '>='
88
102
  - !ruby/object:Gem::Version
89
103
  version: '0'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
- - - '>='
108
+ - - ! '>='
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0'
97
111
  description: Integrates multi-tenancy into a Rails application in a convenient and
@@ -118,6 +132,8 @@ files:
118
132
  - rails/init.rb
119
133
  - spec/acts_as_tenant/configuration_spec.rb
120
134
  - spec/acts_as_tenant/model_extensions_spec.rb
135
+ - spec/acts_as_tenant/tenant_by_filter_spec.rb
136
+ - spec/acts_as_tenant/tenant_by_subdomain_spec.rb
121
137
  - spec/database.yml
122
138
  - spec/spec_helper.rb
123
139
  homepage: http://www.rollcallapp.com/blog
@@ -129,22 +145,24 @@ require_paths:
129
145
  - lib
130
146
  required_ruby_version: !ruby/object:Gem::Requirement
131
147
  requirements:
132
- - - '>='
148
+ - - ! '>='
133
149
  - !ruby/object:Gem::Version
134
150
  version: '0'
135
151
  required_rubygems_version: !ruby/object:Gem::Requirement
136
152
  requirements:
137
- - - '>='
153
+ - - ! '>='
138
154
  - !ruby/object:Gem::Version
139
155
  version: '0'
140
156
  requirements: []
141
157
  rubyforge_project: acts_as_tenant
142
- rubygems_version: 2.0.3
158
+ rubygems_version: 2.2.0
143
159
  signing_key:
144
160
  specification_version: 4
145
161
  summary: Add multi-tenancy to Rails applications using a shared db strategy
146
162
  test_files:
147
163
  - spec/acts_as_tenant/configuration_spec.rb
148
164
  - spec/acts_as_tenant/model_extensions_spec.rb
165
+ - spec/acts_as_tenant/tenant_by_filter_spec.rb
166
+ - spec/acts_as_tenant/tenant_by_subdomain_spec.rb
149
167
  - spec/database.yml
150
168
  - spec/spec_helper.rb