activerecord-multi-tenant 0.3.4 → 0.4.0

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