acts_as_tenant 0.4.3 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 82220bfda9712aaff3d6d06aa5ddbd236290d861
4
- data.tar.gz: a2e325e8ed0ef37fb3a2bf0ab606eeede7e6907b
3
+ metadata.gz: 9820de48ce59a3e8efae341784175dadf04820cf
4
+ data.tar.gz: 28cc62d3e62171c690fd9ba48bbd53c29c5efdc7
5
5
  SHA512:
6
- metadata.gz: e64518b47c7500dad952b6ffe4f1faf5b5d23965fd997fa98bef9a5fd9abd33613dac5b743d8aaec146495d615998d7677d67112efc69387e6d76397e83b1683
7
- data.tar.gz: 535154c7c6ac8e4044fbdc989b931e78fc307027aa154e8b14fc63abd658b76d418d19c0abfbbff3265add12a2a1b861a22fa66f03c89ff419ac1870648ce233
6
+ metadata.gz: aa052469cd82efe7062999976d4782f2240718731331698ced6ceb324646aafd431e15ca66a98d55a398192ab410bf0a0620e962e9128a3daf7220dff871c4f3
7
+ data.tar.gz: 54d961326dedf594be8b87b9603feb063c4ee43a8bb2b8a86a973571b6f01cafd48cc4bd86127ca71771d0e91f275e61549f366c80be425a24df7af1ac1fa3cc
@@ -1,3 +1,10 @@
1
+ 0.4.4
2
+ -----
3
+ * Implement support for polymorphic tenant
4
+ * Ability to use acts_as_tenant with only ActiveRecord (no Rails)
5
+ * Allow setting of custom primary key
6
+ * Bug fixes
7
+
1
8
  0.4.3
2
9
  -----
3
10
  * allow 'optional' relations
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 configuarion options.
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.
@@ -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.5.3')
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
- attr_accessor :default_tenant
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.id]
118
+ keys = [ActsAsTenant.current_tenant.send(pkey)]
103
119
  keys.push(nil) if options[:has_global_records]
104
- where(fkey.to_sym => keys)
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
- Rails::VERSION::MAJOR < 4 ? scoped : all
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
- m.send "#{fkey}=".to_sym, ActsAsTenant.current_tenant.id
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.id
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
@@ -1,3 +1,3 @@
1
1
  module ActsAsTenant
2
- VERSION = "0.4.3"
2
+ VERSION = "0.4.4"
3
3
  end
@@ -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
- before do
203
- @account = Account.create!(name: 'foo')
204
- ActsAsTenant.current_tenant = @account
205
- @project = Project.create!(name: 'project', account: @account)
206
- @comment = Comment.new commentable: @project, account: @account
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
- it { expect(@comment.save!).to eq(true) }
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.3
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: 2018-03-29 00:00:00.000000000 Z
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.5.3
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.5.3
82
+ version: '1.7'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: sqlite3
85
85
  requirement: !ruby/object:Gem::Requirement