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