activerecord-multi-tenant 0.3.4 → 0.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
  SHA1:
3
- metadata.gz: 261f0a075c9a14524dfc43455a030e710bd140a1
4
- data.tar.gz: 3bdd3d5ef7aec6fa07d67a8226a600accb3eeadd
3
+ metadata.gz: 1c30e8a7b37b923b66c5043fb73f3c9e776cea85
4
+ data.tar.gz: 63a2537270723a549cab19a3a75e5c9eaee4fdac
5
5
  SHA512:
6
- metadata.gz: 2b2c5621e0de6308ebc36169873318fd4975e7b54ae7e409a05d58978f65407e8ef6e99e82e2f7399dafdfb659421123cb849e825b93426c28e742ea4ff434a8
7
- data.tar.gz: 0ced6530c9654b4dcfc4d326d6c97a1225d4a47b2300221a8b2fbf05ec3243fc27af128b9da975c73053d23235c333ff79fd10aaf378f7c0f3fb0c844395b4f0
6
+ metadata.gz: 5fe0741bcd4279f6852aa8fc64a25921bb8fb9953cbce564a81ec611602bc0321ca6ededc84ade5053795d64c3e1d3b2a055c6e5c19aa54003ea18c65aa5651e
7
+ data.tar.gz: f59653a116f517ceafdd91677518113299bf86b281259a0816c66299c3ac5b2fa8ec2d347078034ace050adb21aeb12c40ff476e36fe8f9e238f695d99c1f3ad
data/.travis.yml CHANGED
@@ -1,12 +1,11 @@
1
+ sudo: required
2
+ cache: bundler
3
+
1
4
  language: ruby
2
5
 
3
6
  rvm:
4
7
  - 2.1
5
- - 2.2.6
6
8
  - 2.3.3
7
- - 2.4
8
-
9
- script: "bundle exec rake spec"
10
9
 
11
10
  gemfile:
12
11
  - gemfiles/rails_3.2.gemfile
@@ -21,5 +20,12 @@ matrix:
21
20
  - gemfile: gemfiles/rails_5.0.gemfile
22
21
  rvm: 2.1
23
22
 
24
- sudo: false
25
- cache: bundler
23
+ services:
24
+ - docker
25
+
26
+ before_install:
27
+ - docker-compose up -d
28
+ - sleep 5 # wait for postgres to become available
29
+
30
+ script:
31
+ - bundle exec rake spec
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 2017-03-22
4
+
5
+ * Infer multi_tenant setting from parent classes [@webandtech](https://github.com/webandtech) [#6](https://github.com/citusdata/activerecord-multi-tenant/pull/6)
6
+ * Remove use of global tenant klass variable [@webandtech](https://github.com/webandtech) [#6](https://github.com/citusdata/activerecord-multi-tenant/pull/6)
7
+ * Support passing ID values to MultiTenant.with directly [@webandtech](https://github.com/webandtech) [#6](https://github.com/citusdata/activerecord-multi-tenant/pull/6)
8
+ * This effectively deprecates with_id, but we'll keep it around for now
9
+ * Remove unnecessary validation for invalid belongs_to association
10
+
11
+
3
12
  ## 0.3.4 2017-02-22
4
13
 
5
14
  * Expand with_lock workaround to cover lock! as well
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- activerecord-multi-tenant (0.3.4)
4
+ activerecord-multi-tenant (0.4.0)
5
5
  rails (>= 3.1)
6
6
  request_store (>= 1.0.5)
7
7
 
data/README.md CHANGED
@@ -69,7 +69,11 @@ end
69
69
 
70
70
  * **What if I have a table that doesn't relate to my tenant?** (e.g. templates that are the same in every account)
71
71
 
72
- We recommend not using activerecord-multi-tenant on these tables. In case only some records in a table are not associated to a tenant (i.e. your templates are in the same table as actual objects), we recommend setting the tenant_id to 0, and then using MultiTenant.with_id(0) to access these objects.
72
+ We recommend not using activerecord-multi-tenant on these tables. In case only some records in a table are not associated to a tenant (i.e. your templates are in the same table as actual objects), we recommend setting the tenant_id to 0, and then using MultiTenant.with(0) to access these objects.
73
+
74
+ * **What if my tenant model is not defined in my application?**
75
+
76
+ The tenant model does not have to be defined. Use the gem as if the model was present. `MultiTenant.with` accepts either a tenant id or model instance.
73
77
 
74
78
  ## Credits
75
79
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- activerecord-multi-tenant (0.3.4)
4
+ activerecord-multi-tenant (0.4.0)
5
5
  rails (>= 3.1)
6
6
  request_store (>= 1.0.5)
7
7
 
@@ -45,7 +45,7 @@ GEM
45
45
  diff-lcs (1.3)
46
46
  erubis (2.7.0)
47
47
  hike (1.2.3)
48
- i18n (0.8.0)
48
+ i18n (0.8.1)
49
49
  journey (1.0.4)
50
50
  json (1.8.6)
51
51
  mail (2.5.4)
@@ -53,7 +53,7 @@ GEM
53
53
  treetop (~> 1.4.8)
54
54
  mime-types (1.25.1)
55
55
  multi_json (1.12.1)
56
- pg (0.19.0)
56
+ pg (0.20.0)
57
57
  polyglot (0.3.5)
58
58
  power_assert (1.0.1)
59
59
  rack (1.4.7)
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- activerecord-multi-tenant (0.3.4)
4
+ activerecord-multi-tenant (0.4.0)
5
5
  rails (>= 3.1)
6
6
  request_store (>= 1.0.5)
7
7
 
@@ -38,11 +38,11 @@ GEM
38
38
  thor (>= 0.14.0)
39
39
  arel (4.0.2)
40
40
  builder (3.1.4)
41
- concurrent-ruby (1.0.4)
41
+ concurrent-ruby (1.0.5)
42
42
  database_cleaner (1.3.0)
43
43
  diff-lcs (1.3)
44
44
  erubis (2.7.0)
45
- i18n (0.8.0)
45
+ i18n (0.8.1)
46
46
  mail (2.6.4)
47
47
  mime-types (>= 1.16, < 4)
48
48
  mime-types (3.1)
@@ -50,7 +50,7 @@ GEM
50
50
  mime-types-data (3.2016.0521)
51
51
  minitest (4.7.5)
52
52
  multi_json (1.12.1)
53
- pg (0.19.0)
53
+ pg (0.20.0)
54
54
  rack (1.5.5)
55
55
  rack-test (0.6.3)
56
56
  rack (>= 1.0)
@@ -98,7 +98,7 @@ GEM
98
98
  activesupport (>= 3.0)
99
99
  sprockets (>= 2.8, < 4.0)
100
100
  thor (0.19.4)
101
- thread_safe (0.3.5)
101
+ thread_safe (0.3.6)
102
102
  tzinfo (0.3.52)
103
103
 
104
104
  PLATFORMS
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- activerecord-multi-tenant (0.3.4)
4
+ activerecord-multi-tenant (0.4.0)
5
5
  rails (>= 3.1)
6
6
  request_store (>= 1.0.5)
7
7
 
@@ -40,11 +40,11 @@ GEM
40
40
  thor (>= 0.14.0)
41
41
  arel (5.0.1.20140414130214)
42
42
  builder (3.2.3)
43
- concurrent-ruby (1.0.4)
43
+ concurrent-ruby (1.0.5)
44
44
  database_cleaner (1.3.0)
45
45
  diff-lcs (1.3)
46
46
  erubis (2.7.0)
47
- i18n (0.8.0)
47
+ i18n (0.8.1)
48
48
  json (1.8.6)
49
49
  mail (2.6.4)
50
50
  mime-types (>= 1.16, < 4)
@@ -52,7 +52,7 @@ GEM
52
52
  mime-types-data (~> 3.2015)
53
53
  mime-types-data (3.2016.0521)
54
54
  minitest (5.10.1)
55
- pg (0.19.0)
55
+ pg (0.20.0)
56
56
  rack (1.5.5)
57
57
  rack-test (0.6.3)
58
58
  rack (>= 1.0)
@@ -102,7 +102,7 @@ GEM
102
102
  activesupport (>= 3.0)
103
103
  sprockets (>= 2.8, < 4.0)
104
104
  thor (0.19.4)
105
- thread_safe (0.3.5)
105
+ thread_safe (0.3.6)
106
106
  tzinfo (1.2.2)
107
107
  thread_safe (~> 0.1)
108
108
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- activerecord-multi-tenant (0.3.4)
4
+ activerecord-multi-tenant (0.4.0)
5
5
  rails (>= 3.1)
6
6
  request_store (>= 1.0.5)
7
7
 
@@ -48,13 +48,13 @@ GEM
48
48
  thor (>= 0.14.0)
49
49
  arel (6.0.4)
50
50
  builder (3.2.3)
51
- concurrent-ruby (1.0.4)
51
+ concurrent-ruby (1.0.5)
52
52
  database_cleaner (1.3.0)
53
53
  diff-lcs (1.3)
54
54
  erubis (2.7.0)
55
55
  globalid (0.3.7)
56
56
  activesupport (>= 4.1.0)
57
- i18n (0.8.0)
57
+ i18n (0.8.1)
58
58
  loofah (2.0.3)
59
59
  nokogiri (>= 1.5.9)
60
60
  mail (2.6.4)
@@ -64,9 +64,9 @@ GEM
64
64
  mime-types-data (3.2016.0521)
65
65
  mini_portile2 (2.1.0)
66
66
  minitest (5.10.1)
67
- nokogiri (1.7.0.1)
67
+ nokogiri (1.7.1)
68
68
  mini_portile2 (~> 2.1.0)
69
- pg (0.19.0)
69
+ pg (0.20.0)
70
70
  rack (1.6.5)
71
71
  rack-test (0.6.3)
72
72
  rack (>= 1.0)
@@ -125,7 +125,7 @@ GEM
125
125
  activesupport (>= 4.0)
126
126
  sprockets (>= 3.0.0)
127
127
  thor (0.19.4)
128
- thread_safe (0.3.5)
128
+ thread_safe (0.3.6)
129
129
  tzinfo (1.2.2)
130
130
  thread_safe (~> 0.1)
131
131
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- activerecord-multi-tenant (0.3.4)
4
+ activerecord-multi-tenant (0.4.0)
5
5
  rails (>= 3.1)
6
6
  request_store (>= 1.0.5)
7
7
 
@@ -51,13 +51,13 @@ GEM
51
51
  thor (>= 0.14.0)
52
52
  arel (7.1.4)
53
53
  builder (3.2.3)
54
- concurrent-ruby (1.0.4)
54
+ concurrent-ruby (1.0.5)
55
55
  database_cleaner (1.3.0)
56
56
  diff-lcs (1.3)
57
57
  erubis (2.7.0)
58
58
  globalid (0.3.7)
59
59
  activesupport (>= 4.1.0)
60
- i18n (0.8.0)
60
+ i18n (0.8.1)
61
61
  loofah (2.0.3)
62
62
  nokogiri (>= 1.5.9)
63
63
  mail (2.6.4)
@@ -69,9 +69,9 @@ GEM
69
69
  mini_portile2 (2.1.0)
70
70
  minitest (5.10.1)
71
71
  nio4r (1.2.1)
72
- nokogiri (1.7.0.1)
72
+ nokogiri (1.7.1)
73
73
  mini_portile2 (~> 2.1.0)
74
- pg (0.19.0)
74
+ pg (0.20.0)
75
75
  rack (2.0.1)
76
76
  rack-test (0.6.3)
77
77
  rack (>= 1.0)
@@ -129,7 +129,7 @@ GEM
129
129
  activesupport (>= 4.0)
130
130
  sprockets (>= 3.0.0)
131
131
  thor (0.19.4)
132
- thread_safe (0.3.5)
132
+ thread_safe (0.3.6)
133
133
  tzinfo (1.2.2)
134
134
  thread_safe (~> 0.1)
135
135
  websocket-driver (0.6.5)
@@ -1,39 +1,45 @@
1
1
  module MultiTenant
2
2
  module ModelExtensionsClassMethods
3
- def multi_tenant(tenant, options = {})
4
- # Workaround for https://github.com/citusdata/citus/issues/687
5
- if to_s.underscore.to_sym == tenant
6
- before_create -> { self.id ||= self.class.connection.select_value("SELECT nextval('" + [self.class.table_name, self.class.primary_key, 'seq'].join('_') + "'::regclass)") }
7
- end
8
-
9
- # Typically we don't need to run on the tenant model itself
10
- if to_s.underscore.to_sym != tenant
11
- MultiTenant.set_tenant_klass(tenant)
3
+ DEFAULT_ID_FIELD = 'id'.freeze
12
4
 
5
+ def multi_tenant(tenant_name, options = {})
6
+ if to_s.underscore.to_sym == tenant_name
7
+ # This is the tenant model itself. Workaround for https://github.com/citusdata/citus/issues/687
8
+ before_create -> { self.id ||= self.class.connection.select_value("SELECT nextval('" + [self.class.table_name, self.class.primary_key, 'seq'].join('_') + "'::regclass)") }
9
+ else
13
10
  class << self
14
11
  def scoped_by_tenant?
15
12
  true
16
13
  end
17
14
 
15
+ # Allow partition_key to be set from a superclass if not already set in this class
18
16
  def partition_key
19
- @partition_key
17
+ @partition_key ||= ancestors.detect{ |k| k.instance_variable_get(:@partition_key) }
18
+ .try(:instance_variable_get, :@partition_key)
19
+ end
20
+
21
+ # Avoid primary_key errors when using composite primary keys (e.g. id, tenant_id)
22
+ def primary_key
23
+ return @primary_key if @primary_key
24
+ return @primary_key = super || DEFAULT_ID_FIELD if Rails::VERSION::MAJOR < 5
25
+
26
+ primary_object_keys = (connection.schema_cache.primary_keys(table_name) || []) - [partition_key]
27
+ if primary_object_keys.size == 1
28
+ @primary_key = primary_object_keys.first
29
+ else
30
+ @primary_key = DEFAULT_ID_FIELD
31
+ end
20
32
  end
21
33
  end
22
34
 
23
- @partition_key = options[:partition_key] || MultiTenant.partition_key
35
+ @partition_key = options[:partition_key] || MultiTenant.partition_key(tenant_name)
24
36
  partition_key = @partition_key
25
37
 
26
- # Avoid primary_key erroring out with the typical multi-column primary keys that include the partition key
27
- if Rails::VERSION::MAJOR >= 5
28
- primary_object_keys = (connection.schema_cache.primary_keys(table_name) || []) - [partition_key]
29
- self.primary_key = primary_object_keys.first if primary_object_keys.size == 1
30
- else
31
- self.primary_key = 'id' if primary_key.nil?
38
+ # Create an implicit belongs_to association only if tenant class exists
39
+ if MultiTenant.tenant_klass_defined?(tenant_name)
40
+ belongs_to tenant_name, options.slice(:class_name, :inverse_of).merge(foreign_key: partition_key)
32
41
  end
33
42
 
34
- # Create the association
35
- belongs_to tenant, options.slice(:class_name, :inverse_of).merge(foreign_key: partition_key)
36
-
37
43
  # Ensure all queries include the partition key
38
44
  default_scope lambda {
39
45
  if MultiTenant.current_tenant_id
@@ -50,43 +56,26 @@ module MultiTenant
50
56
  end
51
57
  }, on: :create
52
58
 
53
- # Validate that associations belong to the tenant, currently only for belongs_to
54
- polymorphic_foreign_keys = reflect_on_all_associations(:belongs_to).select do |a|
55
- a.options[:polymorphic]
56
- end.map { |a| a.foreign_key }
57
-
58
- reflect_on_all_associations(:belongs_to).each do |a|
59
- unless a == reflect_on_association(tenant) || polymorphic_foreign_keys.include?(a.foreign_key)
60
- association_class = a.options[:class_name].nil? ? a.name.to_s.classify.constantize : a.options[:class_name].constantize
61
- validates_each a.foreign_key.to_sym do |record, attr, value|
62
- primary_key = if association_class.respond_to?(:primary_key)
63
- association_class.primary_key
64
- else
65
- a.primary_key
66
- end.to_sym
67
- record.errors.add attr, 'association is invalid [MultiTenant]' unless value.nil? || association_class.where(primary_key => value).any?
68
- end
69
- end
70
- end
71
-
72
59
  to_include = Module.new do
73
- define_method "#{partition_key}=" do |integer|
74
- write_attribute("#{partition_key}", integer)
60
+ define_method "#{partition_key}=" do |tenant_id|
61
+ write_attribute("#{partition_key}", tenant_id)
75
62
  raise MultiTenant::TenantIsImmutable if send("#{partition_key}_changed?") && persisted? && !send("#{partition_key}_was").nil?
76
- integer
63
+ tenant_id
77
64
  end
78
65
 
79
- define_method "#{MultiTenant.tenant_klass.to_s}=" do |model|
80
- super(model)
81
- raise MultiTenant::TenantIsImmutable if send("#{partition_key}_changed?") && persisted? && !send("#{partition_key}_was").nil?
82
- model
83
- end
66
+ if MultiTenant.tenant_klass_defined?(tenant_name)
67
+ define_method "#{tenant_name}=" do |model|
68
+ super(model)
69
+ raise MultiTenant::TenantIsImmutable if send("#{partition_key}_changed?") && persisted? && !send("#{partition_key}_was").nil?
70
+ model
71
+ end
84
72
 
85
- define_method "#{MultiTenant.tenant_klass.to_s}" do
86
- if !MultiTenant.current_tenant.nil? && !MultiTenant.current_tenant.is_a?(MultiTenant::TenantIdWrapper) && public_send(partition_key) == MultiTenant.current_tenant.id
87
- return MultiTenant.current_tenant
88
- else
89
- super()
73
+ define_method "#{tenant_name}" do
74
+ if !MultiTenant.current_tenant_is_id? && MultiTenant.current_tenant_id && public_send(partition_key) == MultiTenant.current_tenant_id
75
+ return MultiTenant.current_tenant
76
+ else
77
+ super()
78
+ end
90
79
  end
91
80
  end
92
81
  end
@@ -94,7 +83,7 @@ module MultiTenant
94
83
 
95
84
  around_save -> (record, block) {
96
85
  if persisted? && MultiTenant.current_tenant_id.nil?
97
- MultiTenant.with_id(record.public_send(partition_key)) { block.call }
86
+ MultiTenant.with(record.public_send(partition_key)) { block.call }
98
87
  else
99
88
  block.call
100
89
  end
@@ -102,7 +91,7 @@ module MultiTenant
102
91
 
103
92
  around_update -> (record, block) {
104
93
  if MultiTenant.current_tenant_id.nil?
105
- MultiTenant.with_id(record.public_send(partition_key)) { block.call }
94
+ MultiTenant.with(record.public_send(partition_key)) { block.call }
106
95
  else
107
96
  block.call
108
97
  end
@@ -110,7 +99,7 @@ module MultiTenant
110
99
 
111
100
  around_destroy -> (record, block) {
112
101
  if MultiTenant.current_tenant_id.nil?
113
- MultiTenant.with_id(record.public_send(partition_key)) { block.call }
102
+ MultiTenant.with(record.public_send(partition_key)) { block.call }
114
103
  else
115
104
  block.call
116
105
  end
@@ -1,18 +1,12 @@
1
1
  require 'request_store'
2
2
 
3
3
  module MultiTenant
4
- @@tenant_klass = nil
5
-
6
- def self.set_tenant_klass(klass)
7
- @@tenant_klass = klass
8
- end
9
-
10
- def self.tenant_klass
11
- @@tenant_klass
4
+ def self.tenant_klass_defined?(tenant_name)
5
+ !!tenant_name.to_s.classify.safe_constantize
12
6
  end
13
7
 
14
- def self.partition_key
15
- "#{@@tenant_klass.to_s}_id"
8
+ def self.partition_key(tenant_name)
9
+ "#{tenant_name.to_s}_id"
16
10
  end
17
11
 
18
12
  # Workaroud to make "with_lock" work until https://github.com/citusdata/citus/issues/1236 is fixed
@@ -28,43 +22,28 @@ module MultiTenant
28
22
  RequestStore.store[:current_tenant]
29
23
  end
30
24
 
31
- def self.current_tenant_id=(tenant_id)
32
- self.current_tenant = TenantIdWrapper.new(id: tenant_id)
25
+ def self.current_tenant_id
26
+ current_tenant_is_id? ? current_tenant : current_tenant.try(:id)
33
27
  end
34
28
 
35
- def self.current_tenant_id
36
- current_tenant.try(:id)
29
+ def self.current_tenant_is_id?
30
+ current_tenant.is_a?(String) || current_tenant.is_a?(Integer)
37
31
  end
38
32
 
39
33
  def self.with(tenant, &block)
34
+ return block.call if self.current_tenant == tenant
40
35
  old_tenant = self.current_tenant
41
- self.current_tenant = tenant
42
- value = block.call
43
- return value
44
-
45
- ensure
46
- self.current_tenant = old_tenant
47
- end
48
-
49
- def self.with_id(tenant_id, &block)
50
- if MultiTenant.current_tenant_id == tenant_id
51
- block.call
52
- else
53
- MultiTenant.with(TenantIdWrapper.new(id: tenant_id), &block)
36
+ begin
37
+ self.current_tenant = tenant
38
+ return block.call
39
+ ensure
40
+ self.current_tenant = old_tenant
54
41
  end
55
42
  end
56
43
 
57
- class TenantIsImmutable < StandardError
58
- end
59
-
60
- class TenantIdWrapper
61
- attr_reader :id
44
+ # Preserve backward compatibility for people using .with_id
45
+ singleton_class.send(:alias_method, :with_id, :with)
62
46
 
63
- def initialize(id:)
64
- @id = id
65
- end
66
-
67
- def new_record?; true; end
68
- def touch; nil; end
47
+ class TenantIsImmutable < StandardError
69
48
  end
70
49
  end
@@ -1,3 +1,3 @@
1
1
  module MultiTenant
2
- VERSION = '0.3.4'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -56,6 +56,15 @@ describe MultiTenant do
56
56
  it { expect(@custom_partition_key_task.account).to eq(@account) }
57
57
  end
58
58
 
59
+ describe 'Tenant model not defined' do
60
+ before do
61
+ MultiTenant.current_tenant = 77
62
+ @partition_key_not_model_task = PartitionKeyNotModelTask.create! name: 'foo'
63
+ end
64
+
65
+ it { expect(@partition_key_not_model_task.non_model_id).to be 77 }
66
+ end
67
+
59
68
  # Scoping models
60
69
  describe 'Project.all should be scoped to the current tenant if set' do
61
70
  before do
@@ -77,7 +86,7 @@ describe MultiTenant do
77
86
  before do
78
87
  @account = Account.create! name: 'foo'
79
88
  @project = @account.projects.create! name: 'foobar'
80
- MultiTenant.current_tenant= @account1
89
+ MultiTenant.current_tenant = @account1
81
90
  end
82
91
 
83
92
  it { @project.account }
@@ -137,6 +146,40 @@ describe MultiTenant do
137
146
  end
138
147
  end
139
148
 
149
+ describe 'Subclass of Multi Tenant Model' do
150
+ let(:account) { Account.create!(name: 'foo') }
151
+ let(:project) { Project.create!(name: 'project', account: account) }
152
+ let(:task) { project.tasks.create!(name: 'task') }
153
+ let(:sti_task) { StiSubTask.create!(task: task, name: 'sub task') }
154
+
155
+ it 'has partition key' do
156
+ expect(StiSubTask.partition_key).to eq 'account_id'
157
+ expect(StiSubTask.instance_variable_get(:@partition_key)).to eq 'account_id'
158
+ end
159
+
160
+ it 'has primary key' do
161
+ expect(StiSubTask.primary_key).to eq 'id'
162
+ end
163
+
164
+ it 'handles belongs_to through' do
165
+ MultiTenant.with(account) do
166
+ expect(sti_task.project).to eq project
167
+ end
168
+ end
169
+
170
+ it 'handles has_many through' do
171
+ MultiTenant.with(account) do
172
+ expect(project.sub_tasks).to eq [sti_task]
173
+ end
174
+ end
175
+
176
+ it 'handles unscoped' do
177
+ MultiTenant.with(account) do
178
+ expect(StiSubTask.unscoped.find(sti_task.id)).to eq sti_task
179
+ end
180
+ end
181
+ end
182
+
140
183
  # ::with
141
184
  describe "::with" do
142
185
  it "should set current_tenant to the specified tenant inside the block" do
data/spec/schema.rb CHANGED
@@ -28,6 +28,7 @@ ARGV.grep(/\w+_spec\.rb/).empty? && ActiveRecord::Schema.define(version: 1) do
28
28
  t.column :account_id, :integer
29
29
  t.column :name, :string
30
30
  t.column :task_id, :integer
31
+ t.column :type, :string
31
32
  end
32
33
 
33
34
  create_table :countries, force: true do |t|
@@ -55,6 +56,11 @@ ARGV.grep(/\w+_spec\.rb/).empty? && ActiveRecord::Schema.define(version: 1) do
55
56
  t.column :commentable_type, :string
56
57
  end
57
58
 
59
+ create_table :partition_key_not_model_tasks, force: true, partition_key: :non_model_id do |t|
60
+ t.column :non_model_id, :integer
61
+ t.column :name, :string
62
+ end
63
+
58
64
  create_distributed_table :accounts, :id
59
65
  create_distributed_table :projects, :account_id
60
66
  create_distributed_table :managers, :account_id
@@ -63,6 +69,7 @@ ARGV.grep(/\w+_spec\.rb/).empty? && ActiveRecord::Schema.define(version: 1) do
63
69
  create_distributed_table :aliased_tasks, :account_id
64
70
  create_distributed_table :custom_partition_key_tasks, :accountID
65
71
  create_distributed_table :comments, :account_id
72
+ create_distributed_table :partition_key_not_model_tasks, :non_model_id
66
73
  end
67
74
 
68
75
  class Account < ActiveRecord::Base
@@ -104,6 +111,9 @@ class SubTask < ActiveRecord::Base
104
111
  has_one :project, through: :task
105
112
  end
106
113
 
114
+ class StiSubTask < SubTask
115
+ end
116
+
107
117
  class UnscopedModel < ActiveRecord::Base
108
118
  validates_uniqueness_of :name
109
119
  end
@@ -123,6 +133,10 @@ class CustomPartitionKeyTask < ActiveRecord::Base
123
133
  end
124
134
  end
125
135
 
136
+ class PartitionKeyNotModelTask < ActiveRecord::Base
137
+ multi_tenant :non_model
138
+ end
139
+
126
140
  class Comment < ActiveRecord::Base
127
141
  multi_tenant :account
128
142
  belongs_to :commentable, polymorphic: true
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: 0.3.4
4
+ version: 0.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: 2017-02-22 00:00:00.000000000 Z
11
+ date: 2017-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: request_store