activerecord-multi-tenant 2.3.0 → 2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ba7796208980393ca21739d24fa0ac384f0c63ab814041cf46e0216d22eef539
4
- data.tar.gz: 107cea123278629ce9492b15eb6e168549eac4c155fe9a906e57e1695414faf7
3
+ metadata.gz: f277cdbd6175c03dcbbca13e06220f5612fdf40cefb539a3619b4afa0077d369
4
+ data.tar.gz: bae03db825cc60a9833a2287245b7ff5f62ede9aa67497594e867832a75eaedf
5
5
  SHA512:
6
- metadata.gz: c184c2db6316a82d4b092dfdaff1cb69cde80319837302822b7fe8ae387bf627fa6e8670f828d980636e448761e51629c38c53d42dbb505d094f1a2b5eba4b54
7
- data.tar.gz: c021571f18b6072a98bbe0793607077b785a3a989e3365cd45cd7c0d94fb89f5ed30f3129b35199d88aeab653d6c656d20028a84a5ce74bedbaf2a3c6d36c5b6
6
+ metadata.gz: fad6c663f7f588e1359ea4f831b1c66d24de31fa9895aee3ac42d59851597b3ceabf2576c4e2eb49f55baef6eaeb787fee946085b43909450580d4b6a66817cb
7
+ data.tar.gz: c58700fda6a8e99b928435f2bd5abfdc62eb6ccb249ab21350d12f25d9b6ff29860d12451e5e8a77aa2666302d8a9dbfa9bc062dab450ecfdfce2226452c0d43
@@ -51,13 +51,16 @@ jobs:
51
51
  - rails-6.0
52
52
  - rails-6.1
53
53
  - rails-7.0
54
+ - rails-7.1
54
55
  - active-record-6.0
55
56
  - active-record-6.1
56
57
  - active-record-7.0
58
+ - active-record-7.1
57
59
  citus_version:
58
60
  - '10'
59
61
  - '11'
60
-
62
+ - '12'
63
+
61
64
  name: Ruby ${{ matrix.ruby }}/${{ matrix.gemfile }} / Citus ${{ matrix.citus_version }}
62
65
  env:
63
66
  APPRAISAL: ${{ matrix.appraisal }}
data/Appraisals CHANGED
@@ -10,6 +10,10 @@ appraise 'rails-7.0' do
10
10
  gem 'rails', '~> 7.0.0'
11
11
  end
12
12
 
13
+ appraise 'rails-7.1' do
14
+ gem 'rails', '~> 7.1.0.beta1'
15
+ end
16
+
13
17
  appraise 'active-record-6.0' do
14
18
  gem 'activerecord', '~> 6.0.3'
15
19
  end
@@ -21,3 +25,7 @@ end
21
25
  appraise 'active-record-7.0' do
22
26
  gem 'activerecord', '~> 7.0.0'
23
27
  end
28
+
29
+ appraise 'active-record-7.1' do
30
+ gem 'activerecord', '~> 7.1.0.beta1'
31
+ end
data/CHANGELOG.md CHANGED
@@ -1,4 +1,11 @@
1
1
  # Changelog
2
+
3
+ ## 2.4.0 2023-06-05
4
+ * Adds citus 12 to test matrix (#210)
5
+ * Adds Support for rails 7.1 (#208)
6
+ * Fix missing scope in habtm.rb (#207)
7
+ * Update logic inside the tenant_klass_defined? method (#202)
8
+
2
9
  ## 2.3.0 2023-06-05
3
10
  * Adds has_and_belongs_to_many feature with tenant (#193)
4
11
  * Removes eol ruby versions
@@ -8,7 +8,7 @@ alabaster==0.7.13
8
8
  # via sphinx
9
9
  babel==2.12.1
10
10
  # via sphinx
11
- certifi==2023.5.7
11
+ certifi==2023.7.22
12
12
  # via requests
13
13
  charset-normalizer==3.1.0
14
14
  # via requests
@@ -8,9 +8,9 @@ module ActiveRecord
8
8
  module Associations
9
9
  module ClassMethods
10
10
  # rubocop:disable Naming/PredicateName
11
- def has_and_belongs_to_many_with_tenant(name, options = {}, &extension)
11
+ def has_and_belongs_to_many_with_tenant(name, scope = nil, **options, &extension)
12
12
  # rubocop:enable Naming/PredicateName
13
- has_and_belongs_to_many_without_tenant(name, **options, &extension)
13
+ has_and_belongs_to_many_without_tenant(name, scope, **options, &extension)
14
14
 
15
15
  middle_reflection = _reflections[name.to_s].through_reflection
16
16
  join_model = middle_reflection.klass
@@ -67,7 +67,7 @@ module MultiTenant
67
67
  partition_key = @partition_key
68
68
 
69
69
  # Create an implicit belongs_to association only if tenant class exists
70
- if MultiTenant.tenant_klass_defined?(tenant_name)
70
+ if MultiTenant.tenant_klass_defined?(tenant_name, options)
71
71
  belongs_to tenant_name, **options.slice(:class_name, :inverse_of, :optional)
72
72
  .merge(foreign_key: options[:partition_key])
73
73
  end
@@ -103,7 +103,7 @@ module MultiTenant
103
103
  tenant_id
104
104
  end
105
105
 
106
- if MultiTenant.tenant_klass_defined?(tenant_name)
106
+ if MultiTenant.tenant_klass_defined?(tenant_name, options)
107
107
  define_method "#{tenant_name}=" do |model|
108
108
  super(model)
109
109
  if send("#{partition_key}_changed?") && persisted? && !send("#{partition_key}_was").nil?
@@ -5,8 +5,13 @@ module MultiTenant
5
5
  attribute :tenant
6
6
  end
7
7
 
8
- def self.tenant_klass_defined?(tenant_name)
9
- !!tenant_name.to_s.classify.safe_constantize
8
+ def self.tenant_klass_defined?(tenant_name, options = {})
9
+ class_name = if options[:class_name].present?
10
+ options[:class_name]
11
+ else
12
+ tenant_name.to_s.classify
13
+ end
14
+ !!class_name.safe_constantize
10
15
  end
11
16
 
12
17
  def self.partition_key(tenant_name)
@@ -58,9 +63,9 @@ module MultiTenant
58
63
  return nil unless arel.respond_to?(:ast)
59
64
 
60
65
  if arel.ast.relation.is_a? Arel::Nodes::JoinSource
61
- MultiTenant.multi_tenant_model_for_table(arel.ast.relation.left.table_name)
66
+ MultiTenant.multi_tenant_model_for_table(TableNode.table_name(arel.ast.relation.left))
62
67
  else
63
- MultiTenant.multi_tenant_model_for_table(arel.ast.relation.table_name)
68
+ MultiTenant.multi_tenant_model_for_table(TableNode.table_name(arel.ast.relation))
64
69
  end
65
70
  end
66
71
 
@@ -83,7 +83,7 @@ module MultiTenant
83
83
 
84
84
  def visit_Arel_Nodes_Equality(obj, *args)
85
85
  if obj.left.is_a?(Arel::Attributes::Attribute)
86
- table_name = obj.left.relation.table_name
86
+ table_name = MultiTenant::TableNode.table_name(obj.left.relation)
87
87
  model = MultiTenant.multi_tenant_model_for_table(table_name)
88
88
  if model.present? && obj.left.name.to_s == model.partition_key.to_s
89
89
  @current_context.visited_handled_relation(obj.left.relation)
@@ -101,7 +101,7 @@ module MultiTenant
101
101
  end
102
102
 
103
103
  def visit_Arel_Table(obj, _collector = nil)
104
- @current_context.visited_relation(obj) if tenant_relation?(obj.table_name)
104
+ @current_context.visited_relation(obj) if tenant_relation?(MultiTenant::TableNode.table_name(obj))
105
105
  end
106
106
 
107
107
  alias visit_Arel_Nodes_TableAlias visit_Arel_Table
@@ -179,7 +179,9 @@ module MultiTenant
179
179
  def initialize(tenant_attribute)
180
180
  super()
181
181
  @tenant_attribute = tenant_attribute
182
- @tenant_model = MultiTenant.multi_tenant_model_for_table(tenant_attribute.relation.table_name)
182
+ @tenant_model = MultiTenant.multi_tenant_model_for_table(
183
+ MultiTenant::TableNode.table_name(tenant_attribute.relation)
184
+ )
183
185
  end
184
186
 
185
187
  def to_s
@@ -215,7 +217,7 @@ module MultiTenant
215
217
  def initialize(tenant_attribute, table_left)
216
218
  super(tenant_attribute)
217
219
  @table_left = table_left
218
- @model_left = MultiTenant.multi_tenant_model_for_table(table_left.table_name)
220
+ @model_left = MultiTenant.multi_tenant_model_for_table(MultiTenant::TableNode.table_name(table_left))
219
221
  end
220
222
 
221
223
  private
@@ -241,7 +243,7 @@ module MultiTenant
241
243
  module DatabaseStatements
242
244
  def join_to_update(update, *args)
243
245
  update = super(update, *args)
244
- model = MultiTenant.multi_tenant_model_for_table(update.ast.relation.table_name)
246
+ model = MultiTenant.multi_tenant_model_for_table(MultiTenant::TableNode.table_name(update.ast.relation))
245
247
  if model.present? && !MultiTenant.with_write_only_mode_enabled? && MultiTenant.current_tenant_id.present?
246
248
  update.where(MultiTenant::TenantEnforcementClause.new(model.arel_table[model.partition_key]))
247
249
  end
@@ -250,7 +252,7 @@ module MultiTenant
250
252
 
251
253
  def join_to_delete(delete, *args)
252
254
  delete = super(delete, *args)
253
- model = MultiTenant.multi_tenant_model_for_table(delete.ast.left.table_name)
255
+ model = MultiTenant.multi_tenant_model_for_table(MultiTenant::TableNode.table_name(delete.ast.left))
254
256
  if model.present? && !MultiTenant.with_write_only_mode_enabled? && MultiTenant.current_tenant_id.present?
255
257
  delete.where(MultiTenant::TenantEnforcementClause.new(model.arel_table[model.partition_key]))
256
258
  end
@@ -295,7 +297,7 @@ module ActiveRecord
295
297
  node = context.arel_node
296
298
 
297
299
  context.unhandled_relations.each do |relation|
298
- model = MultiTenant.multi_tenant_model_for_table(relation.arel_table.table_name)
300
+ model = MultiTenant.multi_tenant_model_for_table(MultiTenant::TableNode.table_name(relation.arel_table))
299
301
 
300
302
  if MultiTenant.current_tenant_id
301
303
  enforcement_clause = MultiTenant::TenantEnforcementClause.new(relation.arel_table[model.partition_key])
@@ -330,8 +332,8 @@ module ActiveRecord
330
332
 
331
333
  next unless relation_right && relation_left
332
334
 
333
- model_right = MultiTenant.multi_tenant_model_for_table(relation_left.table_name)
334
- model_left = MultiTenant.multi_tenant_model_for_table(relation_right.table_name)
335
+ model_right = MultiTenant.multi_tenant_model_for_table(MultiTenant::TableNode.table_name(relation_left))
336
+ model_left = MultiTenant.multi_tenant_model_for_table(MultiTenant::TableNode.table_name(relation_right))
335
337
  next unless model_right && model_left
336
338
 
337
339
  join_enforcement_clause = MultiTenant::TenantJoinEnforcementClause.new(
@@ -0,0 +1,13 @@
1
+ module MultiTenant
2
+ module TableNode
3
+ # Return table name
4
+ def self.table_name(node)
5
+ # NOTE: Arel::Nodes::Table#table_name is removed in Rails 7.1
6
+ if node.is_a?(Arel::Nodes::TableAlias)
7
+ node.table_name
8
+ else
9
+ node.name
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module MultiTenant
2
- VERSION = '2.3.0'.freeze
2
+ VERSION = '2.4.0'.freeze
3
3
  end
@@ -8,5 +8,6 @@ require_relative 'activerecord-multi-tenant/model_extensions'
8
8
  require_relative 'activerecord-multi-tenant/multi_tenant'
9
9
  require_relative 'activerecord-multi-tenant/query_rewriter'
10
10
  require_relative 'activerecord-multi-tenant/query_monitor'
11
+ require_relative 'activerecord-multi-tenant/table_node'
11
12
  require_relative 'activerecord-multi-tenant/version'
12
13
  require_relative 'activerecord-multi-tenant/habtm'
@@ -64,4 +64,58 @@ RSpec.describe MultiTenant do
64
64
  end
65
65
  end
66
66
  end
67
+
68
+ describe '.tenant_klass_defined?' do
69
+ context 'without options' do
70
+ before(:all) do
71
+ class SampleTenant < ActiveRecord::Base
72
+ multi_tenant :sample_tenant
73
+ end
74
+ end
75
+
76
+ it 'return true with valid tenant_name' do
77
+ expect(MultiTenant.tenant_klass_defined?(:sample_tenant)).to eq(true)
78
+ end
79
+
80
+ it 'return false with invalid_tenant_name' do
81
+ invalid_tenant_name = :tenant
82
+ expect(MultiTenant.tenant_klass_defined?(invalid_tenant_name)).to eq(false)
83
+ end
84
+ end
85
+
86
+ context 'with options' do
87
+ context 'and valid class_name' do
88
+ it 'return true' do
89
+ class SampleTenant < ActiveRecord::Base
90
+ multi_tenant :tenant
91
+ end
92
+
93
+ tenant_name = :tenant
94
+ options = {
95
+ class_name: 'SampleTenant'
96
+ }
97
+ expect(MultiTenant.tenant_klass_defined?(tenant_name, options)).to eq(true)
98
+ end
99
+
100
+ it 'return true when tenant class is nested' do
101
+ module SampleModule
102
+ class SampleNestedTenant < ActiveRecord::Base
103
+ multi_tenant :tenant
104
+ end
105
+ # rubocop:disable Layout/TrailingWhitespace
106
+ # Trailing whitespace is intentionally left here
107
+
108
+ class AnotherTenant < ActiveRecord::Base
109
+ end
110
+ # rubocop:enable Layout/TrailingWhitespace
111
+ end
112
+ tenant_name = :tenant
113
+ options = {
114
+ class_name: 'SampleModule::SampleNestedTenant'
115
+ }
116
+ expect(MultiTenant.tenant_klass_defined?(tenant_name, options)).to eq(true)
117
+ end
118
+ end
119
+ end
120
+ end
67
121
  end
data/spec/schema.rb CHANGED
@@ -174,8 +174,8 @@ end
174
174
  class Manager < ActiveRecord::Base
175
175
  multi_tenant :account
176
176
  belongs_to :project
177
- has_and_belongs_to_many :tasks, { tenant_column: :account_id, tenant_enabled: true,
178
- tenant_class_name: 'Account' }
177
+ has_and_belongs_to_many :tasks, tenant_column: :account_id, tenant_enabled: true,
178
+ tenant_class_name: 'Account'
179
179
  end
180
180
 
181
181
  class Task < ActiveRecord::Base
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-multi-tenant
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Citus Data
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-06 00:00:00.000000000 Z
11
+ date: 2023-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -276,6 +276,7 @@ files:
276
276
  - lib/activerecord-multi-tenant/query_monitor.rb
277
277
  - lib/activerecord-multi-tenant/query_rewriter.rb
278
278
  - lib/activerecord-multi-tenant/sidekiq.rb
279
+ - lib/activerecord-multi-tenant/table_node.rb
279
280
  - lib/activerecord-multi-tenant/version.rb
280
281
  - lib/activerecord_multi_tenant.rb
281
282
  - spec/activerecord-multi-tenant/associations_spec.rb