acts_as_tenant 0.4.3 → 0.4.4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +5 -1
- data/acts_as_tenant.gemspec +1 -1
- data/lib/acts_as_tenant/model_extensions.rb +32 -7
- data/lib/acts_as_tenant/version.rb +1 -1
- data/spec/active_record_models.rb +27 -0
- data/spec/acts_as_tenant/model_extensions_spec.rb +62 -6
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9820de48ce59a3e8efae341784175dadf04820cf
|
4
|
+
data.tar.gz: 28cc62d3e62171c690fd9ba48bbd53c29c5efdc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa052469cd82efe7062999976d4782f2240718731331698ced6ceb324646aafd431e15ca66a98d55a398192ab410bf0a0620e962e9128a3daf7220dff871c4f3
|
7
|
+
data.tar.gz: 54d961326dedf594be8b87b9603feb063c4ee43a8bb2b8a86a973571b6f01cafd48cc4bd86127ca71771d0e91f275e61549f366c80be425a24df7af1ac1fa3cc
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -94,7 +94,7 @@ This is useful in shared routes such as admin panels or internal dashboards when
|
|
94
94
|
|
95
95
|
### Require tenant to be set always ###
|
96
96
|
|
97
|
-
If you want to require the tenant to be set at all times, you can configure acts_as_tenant to raise an error when a query is made without a tenant available. See below under
|
97
|
+
If you want to require the tenant to be set at all times, you can configure acts_as_tenant to raise an error when a query is made without a tenant available. See below under configuration options.
|
98
98
|
|
99
99
|
Scoping your models
|
100
100
|
-------------------
|
@@ -210,6 +210,10 @@ If you have found a bug or want to suggest an improvement, please use our issue
|
|
210
210
|
|
211
211
|
If you want to contribute, fork the project, code your improvements and make a pull request on [Github](http://github.com/ErwinM/acts_as_tenant/). When doing so, please don't forget to add tests. If your contribution is fixing a bug it would be perfect if you could also submit a failing test, illustrating the issue.
|
212
212
|
|
213
|
+
Help maintain this gem
|
214
|
+
----------------------
|
215
|
+
I myself, do not work with RoR much anymore. As a result, I only check this repo a few time a year. If wants to help me maintain this gem on a more regular basis, shoot me a message!
|
216
|
+
|
213
217
|
Author & Credits
|
214
218
|
----------------
|
215
219
|
acts_as_tenant is written by Erwin Matthijssen.
|
data/acts_as_tenant.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
|
25
25
|
s.add_development_dependency('rspec', '>=3.0')
|
26
26
|
s.add_development_dependency('rspec-rails')
|
27
|
-
s.add_development_dependency('database_cleaner', '~> 1.
|
27
|
+
s.add_development_dependency('database_cleaner', '~> 1.7')
|
28
28
|
s.add_development_dependency('sqlite3')
|
29
29
|
#s.add_development_dependency('mongoid', '~> 4.0')
|
30
30
|
|
@@ -22,6 +22,14 @@ module ActsAsTenant
|
|
22
22
|
"#{@@tenant_klass.to_s}_id"
|
23
23
|
end
|
24
24
|
|
25
|
+
def self.pkey
|
26
|
+
:id
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.polymorphic_type
|
30
|
+
"#{@@tenant_klass.to_s}_type"
|
31
|
+
end
|
32
|
+
|
25
33
|
def self.current_tenant=(tenant)
|
26
34
|
RequestStore.store[:current_tenant] = tenant
|
27
35
|
end
|
@@ -43,7 +51,13 @@ module ActsAsTenant
|
|
43
51
|
end
|
44
52
|
|
45
53
|
class << self
|
46
|
-
|
54
|
+
def default_tenant=(tenant)
|
55
|
+
@default_tenant = tenant
|
56
|
+
end
|
57
|
+
|
58
|
+
def default_tenant
|
59
|
+
@default_tenant unless unscoped
|
60
|
+
end
|
47
61
|
end
|
48
62
|
|
49
63
|
def self.with_tenant(tenant, &block)
|
@@ -90,8 +104,10 @@ module ActsAsTenant
|
|
90
104
|
ActsAsTenant.add_global_record_model(self) if options[:has_global_records]
|
91
105
|
|
92
106
|
# Create the association
|
93
|
-
valid_options = options.slice(:foreign_key, :class_name, :inverse_of, :optional)
|
107
|
+
valid_options = options.slice(:foreign_key, :class_name, :inverse_of, :optional, :primary_key)
|
94
108
|
fkey = valid_options[:foreign_key] || ActsAsTenant.fkey
|
109
|
+
pkey = valid_options[:primary_key] || ActsAsTenant.pkey
|
110
|
+
polymorphic_type = valid_options[:foreign_type] || ActsAsTenant.polymorphic_type
|
95
111
|
belongs_to tenant, valid_options
|
96
112
|
|
97
113
|
default_scope lambda {
|
@@ -99,11 +115,14 @@ module ActsAsTenant
|
|
99
115
|
raise ActsAsTenant::Errors::NoTenantSet
|
100
116
|
end
|
101
117
|
if ActsAsTenant.current_tenant
|
102
|
-
keys = [ActsAsTenant.current_tenant.
|
118
|
+
keys = [ActsAsTenant.current_tenant.send(pkey)]
|
103
119
|
keys.push(nil) if options[:has_global_records]
|
104
|
-
|
120
|
+
|
121
|
+
query_criteria = { fkey.to_sym => keys }
|
122
|
+
query_criteria.merge!({ polymorphic_type.to_sym => ActsAsTenant.current_tenant.class.to_s }) if options[:polymorphic]
|
123
|
+
where(query_criteria)
|
105
124
|
else
|
106
|
-
|
125
|
+
ActiveRecord::VERSION::MAJOR < 4 ? scoped : all
|
107
126
|
end
|
108
127
|
}
|
109
128
|
|
@@ -113,7 +132,12 @@ module ActsAsTenant
|
|
113
132
|
#
|
114
133
|
before_validation Proc.new {|m|
|
115
134
|
if ActsAsTenant.current_tenant
|
116
|
-
|
135
|
+
if options[:polymorphic]
|
136
|
+
m.send("#{fkey}=".to_sym, ActsAsTenant.current_tenant.class.to_s) if m.send("#{fkey}").nil?
|
137
|
+
m.send("#{polymorphic_type}=".to_sym, ActsAsTenant.current_tenant.class.to_s) if m.send("#{polymorphic_type}").nil?
|
138
|
+
else
|
139
|
+
m.send "#{fkey}=".to_sym, ActsAsTenant.current_tenant.send(pkey)
|
140
|
+
end
|
117
141
|
end
|
118
142
|
}, :on => :create
|
119
143
|
|
@@ -153,7 +177,7 @@ module ActsAsTenant
|
|
153
177
|
end
|
154
178
|
|
155
179
|
define_method "#{ActsAsTenant.tenant_klass.to_s}" do
|
156
|
-
if !ActsAsTenant.current_tenant.nil? && send(fkey) == ActsAsTenant.current_tenant.
|
180
|
+
if !ActsAsTenant.current_tenant.nil? && send(fkey) == ActsAsTenant.current_tenant.send(pkey)
|
157
181
|
return ActsAsTenant.current_tenant
|
158
182
|
else
|
159
183
|
super()
|
@@ -172,6 +196,7 @@ module ActsAsTenant
|
|
172
196
|
def validates_uniqueness_to_tenant(fields, args ={})
|
173
197
|
raise ActsAsTenant::Errors::ModelNotScopedByTenant unless respond_to?(:scoped_by_tenant?)
|
174
198
|
fkey = reflect_on_association(ActsAsTenant.tenant_klass).foreign_key
|
199
|
+
pkey = reflect_on_association(ActsAsTenant.tenant_klass).active_record_primary_key
|
175
200
|
#tenant_id = lambda { "#{ActsAsTenant.fkey}"}.call
|
176
201
|
if args[:scope]
|
177
202
|
args[:scope] = Array(args[:scope]) << fkey
|
@@ -49,12 +49,22 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
49
49
|
t.column :accountID, :integer
|
50
50
|
end
|
51
51
|
|
52
|
+
create_table :articles, :force => true do |t|
|
53
|
+
t.column :title, :string
|
54
|
+
end
|
55
|
+
|
52
56
|
create_table :comments, :force => true do |t|
|
53
57
|
t.column :commentable_id, :integer
|
54
58
|
t.column :commentable_type, :string
|
55
59
|
t.column :account_id, :integer
|
56
60
|
end
|
57
61
|
|
62
|
+
create_table :polymorphic_tenant_comments, :force => true do |t|
|
63
|
+
t.column :polymorphic_tenant_commentable_id, :integer
|
64
|
+
t.column :polymorphic_tenant_commentable_type, :string
|
65
|
+
t.column :account_id, :integer
|
66
|
+
end
|
67
|
+
|
58
68
|
end
|
59
69
|
|
60
70
|
class Account < ActiveRecord::Base
|
@@ -64,6 +74,7 @@ end
|
|
64
74
|
class Project < ActiveRecord::Base
|
65
75
|
has_one :manager
|
66
76
|
has_many :tasks
|
77
|
+
has_many :polymorphic_tenant_comments, as: :polymorphic_tenant_commentable
|
67
78
|
acts_as_tenant :account
|
68
79
|
|
69
80
|
validates_uniqueness_to_tenant :name
|
@@ -102,12 +113,28 @@ class CustomForeignKeyTask < ActiveRecord::Base
|
|
102
113
|
validates_uniqueness_to_tenant :name
|
103
114
|
end
|
104
115
|
|
116
|
+
class CustomPrimaryKeyTask < ActiveRecord::Base
|
117
|
+
self.table_name = 'projects'
|
118
|
+
acts_as_tenant(:account, :foreign_key => "name", :primary_key => "name")
|
119
|
+
validates_presence_of :name
|
120
|
+
end
|
121
|
+
|
105
122
|
class Comment < ActiveRecord::Base
|
106
123
|
belongs_to :commentable, polymorphic: true
|
107
124
|
belongs_to :task, -> { where(comments: { commentable_type: 'Task' }) }, foreign_key: 'commentable_id'
|
108
125
|
acts_as_tenant :account
|
109
126
|
end
|
110
127
|
|
128
|
+
class Article < ActiveRecord::Base
|
129
|
+
has_many :polymorphic_tenant_comments, as: :polymorphic_tenant_commentable
|
130
|
+
end
|
131
|
+
|
132
|
+
class PolymorphicTenantComment < ActiveRecord::Base
|
133
|
+
belongs_to :polymorphic_tenant_commentable, polymorphic: true
|
134
|
+
belongs_to :account
|
135
|
+
acts_as_tenant :polymorphic_tenant_commentable, polymorphic: true
|
136
|
+
end
|
137
|
+
|
111
138
|
class GlobalProject < ActiveRecord::Base
|
112
139
|
self.table_name = 'projects'
|
113
140
|
|
@@ -73,6 +73,18 @@ describe ActsAsTenant do
|
|
73
73
|
it { expect(@custom_foreign_key_task.account).to eq(@account) }
|
74
74
|
end
|
75
75
|
|
76
|
+
describe 'Handles custom primary_key on tenant model' do
|
77
|
+
before do
|
78
|
+
@account = Account.create!(:name => 'foo')
|
79
|
+
CustomPrimaryKeyTask.create!(name: 'bar')
|
80
|
+
ActsAsTenant.current_tenant = @account
|
81
|
+
@custom_primary_key_task = CustomPrimaryKeyTask.create!
|
82
|
+
end
|
83
|
+
|
84
|
+
it { expect(@custom_primary_key_task.account).to eq(@account) }
|
85
|
+
it { expect(CustomPrimaryKeyTask.count).to eq(1) }
|
86
|
+
end
|
87
|
+
|
76
88
|
# Scoping models
|
77
89
|
describe 'Project.all should be scoped to the current tenant if set' do
|
78
90
|
before do
|
@@ -199,14 +211,46 @@ describe ActsAsTenant do
|
|
199
211
|
end
|
200
212
|
|
201
213
|
describe "It should be possible to use associations with foreign_key from polymorphic" do
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
214
|
+
context 'tenanted objects have a polymorphic association' do
|
215
|
+
before do
|
216
|
+
@account = Account.create!(name: 'foo')
|
217
|
+
ActsAsTenant.current_tenant = @account
|
218
|
+
@project = Project.create!(name: 'project', account: @account)
|
219
|
+
@comment = Comment.new commentable: @project, account: @account
|
220
|
+
end
|
221
|
+
|
222
|
+
it { expect(@comment.save!).to eq(true) }
|
207
223
|
end
|
208
224
|
|
209
|
-
|
225
|
+
context 'tenant is polymorphic' do
|
226
|
+
before do
|
227
|
+
@account = Account.create!(name: 'foo')
|
228
|
+
@project = Project.create!(name: 'polymorphic project')
|
229
|
+
ActsAsTenant.current_tenant = @project
|
230
|
+
@comment = PolymorphicTenantComment.new(account: @account)
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'populates commentable_type with the current tenant' do
|
234
|
+
expect(@comment.polymorphic_tenant_commentable_id).to eql(@project.id)
|
235
|
+
expect(@comment.polymorphic_tenant_commentable_type).to eql(@project.class.to_s)
|
236
|
+
end
|
237
|
+
|
238
|
+
context 'with another type of tenant, same id' do
|
239
|
+
before do
|
240
|
+
@comment.save!
|
241
|
+
@article = Article.create!(id: @project.id, title: 'article title')
|
242
|
+
@comment_on_article = @article.polymorphic_tenant_comments.create!
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'correctly scopes to the current tenant type' do
|
246
|
+
expect(@comment_on_article).to be_persisted
|
247
|
+
expect(@comment).to be_persisted
|
248
|
+
expect(PolymorphicTenantComment.count).to eql(1)
|
249
|
+
expect(PolymorphicTenantComment.all.first.attributes).to eql(@comment.attributes)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
210
254
|
end
|
211
255
|
|
212
256
|
# Additional default_scopes
|
@@ -315,6 +359,18 @@ describe ActsAsTenant do
|
|
315
359
|
end
|
316
360
|
end
|
317
361
|
|
362
|
+
it "should set current_tenant to nil even if default_tenant is set" do
|
363
|
+
begin
|
364
|
+
old_default_tenant = ActsAsTenant.default_tenant
|
365
|
+
ActsAsTenant.default_tenant = Account.create!(name: 'foo')
|
366
|
+
ActsAsTenant.without_tenant do
|
367
|
+
expect(ActsAsTenant.current_tenant).to be_nil
|
368
|
+
end
|
369
|
+
ensure
|
370
|
+
ActsAsTenant.default_tenant = old_default_tenant
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
318
374
|
it "should reset current_tenant to the previous tenant once exiting the block" do
|
319
375
|
@account1 = Account.create!(:name => 'foo')
|
320
376
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: acts_as_tenant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Erwin Matthijssen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: request_store
|
@@ -72,14 +72,14 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 1.
|
75
|
+
version: '1.7'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 1.
|
82
|
+
version: '1.7'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: sqlite3
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|