activerecord-multi-tenant 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/Gemfile.lock +14 -4
- data/activerecord-multi-tenant.gemspec +1 -0
- data/docker-compose.yml +3 -3
- data/gemfiles/active_record_5.1.gemfile.lock +13 -3
- data/gemfiles/rails_3.2.gemfile.lock +14 -3
- data/gemfiles/rails_4.0.gemfile.lock +13 -3
- data/gemfiles/rails_4.1.gemfile.lock +13 -3
- data/gemfiles/rails_4.2.gemfile.lock +13 -3
- data/gemfiles/rails_5.0.gemfile.lock +13 -3
- data/gemfiles/rails_5.1.gemfile.lock +13 -3
- data/lib/activerecord-multi-tenant/fast_truncate.rb +1 -1
- data/lib/activerecord-multi-tenant/migrations.rb +2 -0
- data/lib/activerecord-multi-tenant/model_extensions.rb +8 -3
- data/lib/activerecord-multi-tenant/query_rewriter.rb +86 -20
- data/lib/activerecord-multi-tenant/sidekiq.rb +1 -2
- data/lib/activerecord-multi-tenant/version.rb +1 -1
- data/spec/activerecord-multi-tenant/fast_truncate_spec.rb +23 -0
- data/spec/activerecord-multi-tenant/model_extensions_spec.rb +62 -13
- data/spec/activerecord-multi-tenant/sidekiq_spec.rb +24 -0
- data/spec/schema.rb +15 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ad5f8df62dcf4cb4308e7b52736ba20212cc154
|
4
|
+
data.tar.gz: 244c9cdcd00b6d62a982a9dfa6917dade6aacf60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2cde81a900904e331d3f4558b5ebfbb55547bebef5ec841087081a23598bcc89bbbd7d077fab260cc70a0fb5b0aa8ab535d4b89040cb4f784b6299e2d27231c
|
7
|
+
data.tar.gz: 406344742c98800907c67436dc7d711e85a11d73d78b262504586de9c0a943cef854181493f6985dac3a0dcf5feb902ddff00b0ea0f323edfb5446d846483bad
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.7.0 2017-07-18
|
4
|
+
|
5
|
+
* Switch back to Relation-based mechanism of hooking into ActiveRecord (this resolves issues for simple queries that didn't get rewritten)
|
6
|
+
* Query rewriter improvements
|
7
|
+
* Handle OUTER JOIN correctly
|
8
|
+
* Correctly rewrite sub-selects
|
9
|
+
* Model tenant method: Only return cached object if not loaded
|
10
|
+
* Fix support for inherited model classes that only have `multi-tenant` on a higher level object [Aaron Severs](https://github.com/webandtech) [#13](https://github.com/citusdata/activerecord-multi-tenant/pull/13)
|
11
|
+
* Sidekiq middleware: Don't automatically perform a find for the tenant object for every job [Scott Mitchell](https://github.com/smitchelus) [#14](https://github.com/citusdata/activerecord-multi-tenant/pull/14)
|
12
|
+
* Fix automatic inverse of on singular associations [Kyle Bock](https://github.com/kwbock) [#15](https://github.com/citusdata/activerecord-multi-tenant/pull/15)
|
13
|
+
* Fix bug that prevents fast truncate from running [Kyle Bock](https://github.com/kwbock) [#17](https://github.com/citusdata/activerecord-multi-tenant/pull/17)
|
14
|
+
|
15
|
+
|
3
16
|
## 0.6.0 2017-06-09
|
4
17
|
|
5
18
|
* Query rewriter
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
activerecord-multi-tenant (0.
|
4
|
+
activerecord-multi-tenant (0.7.0)
|
5
5
|
rails (>= 3.1)
|
6
6
|
request_store (>= 1.0.5)
|
7
7
|
|
@@ -52,6 +52,7 @@ GEM
|
|
52
52
|
arel (7.1.4)
|
53
53
|
builder (3.2.2)
|
54
54
|
concurrent-ruby (1.0.4)
|
55
|
+
connection_pool (2.2.1)
|
55
56
|
diff-lcs (1.2.5)
|
56
57
|
erubis (2.7.0)
|
57
58
|
globalid (0.4.0)
|
@@ -72,6 +73,8 @@ GEM
|
|
72
73
|
mini_portile2 (~> 2.1.0)
|
73
74
|
pg (0.19.0)
|
74
75
|
rack (2.0.1)
|
76
|
+
rack-protection (1.5.3)
|
77
|
+
rack
|
75
78
|
rack-test (0.6.3)
|
76
79
|
rack (>= 1.0)
|
77
80
|
rails (5.0.1)
|
@@ -98,6 +101,7 @@ GEM
|
|
98
101
|
rake (>= 0.8.7)
|
99
102
|
thor (>= 0.18.1, < 2.0)
|
100
103
|
rake (12.0.0)
|
104
|
+
redis (3.3.3)
|
101
105
|
request_store (1.3.2)
|
102
106
|
rspec (3.5.0)
|
103
107
|
rspec-core (~> 3.5.0)
|
@@ -120,6 +124,11 @@ GEM
|
|
120
124
|
rspec-mocks (~> 3.5.0)
|
121
125
|
rspec-support (~> 3.5.0)
|
122
126
|
rspec-support (3.5.0)
|
127
|
+
sidekiq (4.2.10)
|
128
|
+
concurrent-ruby (~> 1.0)
|
129
|
+
connection_pool (~> 2.2, >= 2.2.0)
|
130
|
+
rack-protection (>= 1.5.0)
|
131
|
+
redis (~> 3.2, >= 3.2.1)
|
123
132
|
sprockets (3.7.1)
|
124
133
|
concurrent-ruby (~> 1.0)
|
125
134
|
rack (> 1, < 3)
|
@@ -128,8 +137,8 @@ GEM
|
|
128
137
|
activesupport (>= 4.0)
|
129
138
|
sprockets (>= 3.0.0)
|
130
139
|
thor (0.19.4)
|
131
|
-
thread_safe (0.3.
|
132
|
-
tzinfo (1.2.
|
140
|
+
thread_safe (0.3.6)
|
141
|
+
tzinfo (1.2.3)
|
133
142
|
thread_safe (~> 0.1)
|
134
143
|
websocket-driver (0.6.5)
|
135
144
|
websocket-extensions (>= 0.1.0)
|
@@ -145,7 +154,8 @@ DEPENDENCIES
|
|
145
154
|
rake
|
146
155
|
rspec (>= 3.0)
|
147
156
|
rspec-rails
|
157
|
+
sidekiq
|
148
158
|
thor
|
149
159
|
|
150
160
|
BUNDLED WITH
|
151
|
-
1.
|
161
|
+
1.15.1
|
data/docker-compose.yml
CHANGED
@@ -2,15 +2,15 @@ version: '2'
|
|
2
2
|
|
3
3
|
services:
|
4
4
|
master:
|
5
|
-
image: 'citusdata/citus:6.2.
|
5
|
+
image: 'citusdata/citus:6.2.3'
|
6
6
|
ports: ['5600:5432']
|
7
7
|
labels: ['com.citusdata.role=Master']
|
8
8
|
volumes: ['/var/run/postgresql']
|
9
9
|
worker1:
|
10
|
-
image: 'citusdata/citus:6.2.
|
10
|
+
image: 'citusdata/citus:6.2.3'
|
11
11
|
labels: ['com.citusdata.role=Worker']
|
12
12
|
worker2:
|
13
|
-
image: 'citusdata/citus:6.2.
|
13
|
+
image: 'citusdata/citus:6.2.3'
|
14
14
|
labels: ['com.citusdata.role=Worker']
|
15
15
|
config:
|
16
16
|
image: 'citusdata/workerlist-gen:2.0.0'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
|
-
remote:
|
2
|
+
remote: ..
|
3
3
|
specs:
|
4
|
-
activerecord-multi-tenant (0.
|
4
|
+
activerecord-multi-tenant (0.7.0)
|
5
5
|
rails (>= 3.1)
|
6
6
|
request_store (>= 1.0.5)
|
7
7
|
|
@@ -52,6 +52,7 @@ GEM
|
|
52
52
|
arel (8.0.0)
|
53
53
|
builder (3.2.3)
|
54
54
|
concurrent-ruby (1.0.5)
|
55
|
+
connection_pool (2.2.1)
|
55
56
|
diff-lcs (1.3)
|
56
57
|
erubi (1.6.0)
|
57
58
|
globalid (0.4.0)
|
@@ -72,6 +73,8 @@ GEM
|
|
72
73
|
mini_portile2 (~> 2.1.0)
|
73
74
|
pg (0.20.0)
|
74
75
|
rack (2.0.1)
|
76
|
+
rack-protection (1.5.3)
|
77
|
+
rack
|
75
78
|
rack-test (0.6.3)
|
76
79
|
rack (>= 1.0)
|
77
80
|
rails (5.1.0)
|
@@ -98,6 +101,7 @@ GEM
|
|
98
101
|
rake (>= 0.8.7)
|
99
102
|
thor (>= 0.18.1, < 2.0)
|
100
103
|
rake (12.0.0)
|
104
|
+
redis (3.3.3)
|
101
105
|
request_store (1.3.2)
|
102
106
|
rspec (3.6.0)
|
103
107
|
rspec-core (~> 3.6.0)
|
@@ -120,6 +124,11 @@ GEM
|
|
120
124
|
rspec-mocks (~> 3.6.0)
|
121
125
|
rspec-support (~> 3.6.0)
|
122
126
|
rspec-support (3.6.0)
|
127
|
+
sidekiq (4.2.10)
|
128
|
+
concurrent-ruby (~> 1.0)
|
129
|
+
connection_pool (~> 2.2, >= 2.2.0)
|
130
|
+
rack-protection (>= 1.5.0)
|
131
|
+
redis (~> 3.2, >= 3.2.1)
|
123
132
|
sprockets (3.7.1)
|
124
133
|
concurrent-ruby (~> 1.0)
|
125
134
|
rack (> 1, < 3)
|
@@ -146,7 +155,8 @@ DEPENDENCIES
|
|
146
155
|
rake
|
147
156
|
rspec (>= 3.0)
|
148
157
|
rspec-rails
|
158
|
+
sidekiq
|
149
159
|
thor
|
150
160
|
|
151
161
|
BUNDLED WITH
|
152
|
-
1.
|
162
|
+
1.15.1
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
|
-
remote:
|
2
|
+
remote: ..
|
3
3
|
specs:
|
4
|
-
activerecord-multi-tenant (0.
|
4
|
+
activerecord-multi-tenant (0.7.0)
|
5
5
|
rails (>= 3.1)
|
6
6
|
request_store (>= 1.0.5)
|
7
7
|
|
@@ -41,6 +41,8 @@ GEM
|
|
41
41
|
thor (>= 0.14.0)
|
42
42
|
arel (3.0.3)
|
43
43
|
builder (3.0.4)
|
44
|
+
concurrent-ruby (1.0.5)
|
45
|
+
connection_pool (2.2.1)
|
44
46
|
diff-lcs (1.3)
|
45
47
|
erubis (2.7.0)
|
46
48
|
hike (1.2.3)
|
@@ -58,6 +60,8 @@ GEM
|
|
58
60
|
rack (1.4.7)
|
59
61
|
rack-cache (1.7.0)
|
60
62
|
rack (>= 0.4)
|
63
|
+
rack-protection (2.0.0)
|
64
|
+
rack
|
61
65
|
rack-ssl (1.3.4)
|
62
66
|
rack
|
63
67
|
rack-test (0.6.3)
|
@@ -80,6 +84,7 @@ GEM
|
|
80
84
|
rake (12.0.0)
|
81
85
|
rdoc (3.12.2)
|
82
86
|
json (~> 1.4)
|
87
|
+
redis (3.3.3)
|
83
88
|
request_store (1.3.2)
|
84
89
|
rspec (3.5.0)
|
85
90
|
rspec-core (~> 3.5.0)
|
@@ -102,6 +107,11 @@ GEM
|
|
102
107
|
rspec-mocks (~> 3.5.0)
|
103
108
|
rspec-support (~> 3.5.0)
|
104
109
|
rspec-support (3.5.0)
|
110
|
+
sidekiq (5.0.3)
|
111
|
+
concurrent-ruby (~> 1.0)
|
112
|
+
connection_pool (~> 2.2, >= 2.2.0)
|
113
|
+
rack-protection (>= 1.5.0)
|
114
|
+
redis (~> 3.3, >= 3.3.3)
|
105
115
|
sprockets (2.2.3)
|
106
116
|
hike (~> 1.2)
|
107
117
|
multi_json (~> 1.0)
|
@@ -127,8 +137,9 @@ DEPENDENCIES
|
|
127
137
|
rake
|
128
138
|
rspec (>= 3.0)
|
129
139
|
rspec-rails
|
140
|
+
sidekiq
|
130
141
|
test-unit (~> 3.0)
|
131
142
|
thor
|
132
143
|
|
133
144
|
BUNDLED WITH
|
134
|
-
1.
|
145
|
+
1.15.1
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
|
-
remote:
|
2
|
+
remote: ..
|
3
3
|
specs:
|
4
|
-
activerecord-multi-tenant (0.
|
4
|
+
activerecord-multi-tenant (0.7.0)
|
5
5
|
rails (>= 3.1)
|
6
6
|
request_store (>= 1.0.5)
|
7
7
|
|
@@ -39,6 +39,7 @@ GEM
|
|
39
39
|
arel (4.0.2)
|
40
40
|
builder (3.1.4)
|
41
41
|
concurrent-ruby (1.0.5)
|
42
|
+
connection_pool (2.2.1)
|
42
43
|
diff-lcs (1.3)
|
43
44
|
erubis (2.7.0)
|
44
45
|
i18n (0.8.1)
|
@@ -51,6 +52,8 @@ GEM
|
|
51
52
|
multi_json (1.12.1)
|
52
53
|
pg (0.20.0)
|
53
54
|
rack (1.5.5)
|
55
|
+
rack-protection (2.0.0)
|
56
|
+
rack
|
54
57
|
rack-test (0.6.3)
|
55
58
|
rack (>= 1.0)
|
56
59
|
rails (4.0.13)
|
@@ -67,6 +70,7 @@ GEM
|
|
67
70
|
rake (>= 0.8.7)
|
68
71
|
thor (>= 0.18.1, < 2.0)
|
69
72
|
rake (12.0.0)
|
73
|
+
redis (3.3.3)
|
70
74
|
request_store (1.3.2)
|
71
75
|
rspec (3.5.0)
|
72
76
|
rspec-core (~> 3.5.0)
|
@@ -89,6 +93,11 @@ GEM
|
|
89
93
|
rspec-mocks (~> 3.5.0)
|
90
94
|
rspec-support (~> 3.5.0)
|
91
95
|
rspec-support (3.5.0)
|
96
|
+
sidekiq (5.0.3)
|
97
|
+
concurrent-ruby (~> 1.0)
|
98
|
+
connection_pool (~> 2.2, >= 2.2.0)
|
99
|
+
rack-protection (>= 1.5.0)
|
100
|
+
redis (~> 3.3, >= 3.3.3)
|
92
101
|
sprockets (3.7.1)
|
93
102
|
concurrent-ruby (~> 1.0)
|
94
103
|
rack (> 1, < 3)
|
@@ -111,7 +120,8 @@ DEPENDENCIES
|
|
111
120
|
rake
|
112
121
|
rspec (>= 3.0)
|
113
122
|
rspec-rails
|
123
|
+
sidekiq
|
114
124
|
thor
|
115
125
|
|
116
126
|
BUNDLED WITH
|
117
|
-
1.
|
127
|
+
1.15.1
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
|
-
remote:
|
2
|
+
remote: ..
|
3
3
|
specs:
|
4
|
-
activerecord-multi-tenant (0.
|
4
|
+
activerecord-multi-tenant (0.7.0)
|
5
5
|
rails (>= 3.1)
|
6
6
|
request_store (>= 1.0.5)
|
7
7
|
|
@@ -41,6 +41,7 @@ GEM
|
|
41
41
|
arel (5.0.1.20140414130214)
|
42
42
|
builder (3.2.3)
|
43
43
|
concurrent-ruby (1.0.5)
|
44
|
+
connection_pool (2.2.1)
|
44
45
|
diff-lcs (1.3)
|
45
46
|
erubis (2.7.0)
|
46
47
|
i18n (0.8.1)
|
@@ -53,6 +54,8 @@ GEM
|
|
53
54
|
minitest (5.10.1)
|
54
55
|
pg (0.20.0)
|
55
56
|
rack (1.5.5)
|
57
|
+
rack-protection (2.0.0)
|
58
|
+
rack
|
56
59
|
rack-test (0.6.3)
|
57
60
|
rack (>= 1.0)
|
58
61
|
rails (4.1.16)
|
@@ -71,6 +74,7 @@ GEM
|
|
71
74
|
rake (>= 0.8.7)
|
72
75
|
thor (>= 0.18.1, < 2.0)
|
73
76
|
rake (12.0.0)
|
77
|
+
redis (3.3.3)
|
74
78
|
request_store (1.3.2)
|
75
79
|
rspec (3.5.0)
|
76
80
|
rspec-core (~> 3.5.0)
|
@@ -93,6 +97,11 @@ GEM
|
|
93
97
|
rspec-mocks (~> 3.5.0)
|
94
98
|
rspec-support (~> 3.5.0)
|
95
99
|
rspec-support (3.5.0)
|
100
|
+
sidekiq (5.0.3)
|
101
|
+
concurrent-ruby (~> 1.0)
|
102
|
+
connection_pool (~> 2.2, >= 2.2.0)
|
103
|
+
rack-protection (>= 1.5.0)
|
104
|
+
redis (~> 3.3, >= 3.3.3)
|
96
105
|
sprockets (3.7.1)
|
97
106
|
concurrent-ruby (~> 1.0)
|
98
107
|
rack (> 1, < 3)
|
@@ -116,7 +125,8 @@ DEPENDENCIES
|
|
116
125
|
rake
|
117
126
|
rspec (>= 3.0)
|
118
127
|
rspec-rails
|
128
|
+
sidekiq
|
119
129
|
thor
|
120
130
|
|
121
131
|
BUNDLED WITH
|
122
|
-
1.
|
132
|
+
1.15.1
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
|
-
remote:
|
2
|
+
remote: ..
|
3
3
|
specs:
|
4
|
-
activerecord-multi-tenant (0.
|
4
|
+
activerecord-multi-tenant (0.7.0)
|
5
5
|
rails (>= 3.1)
|
6
6
|
request_store (>= 1.0.5)
|
7
7
|
|
@@ -49,6 +49,7 @@ GEM
|
|
49
49
|
arel (6.0.4)
|
50
50
|
builder (3.2.3)
|
51
51
|
concurrent-ruby (1.0.5)
|
52
|
+
connection_pool (2.2.1)
|
52
53
|
diff-lcs (1.3)
|
53
54
|
erubis (2.7.0)
|
54
55
|
globalid (0.3.7)
|
@@ -67,6 +68,8 @@ GEM
|
|
67
68
|
mini_portile2 (~> 2.1.0)
|
68
69
|
pg (0.20.0)
|
69
70
|
rack (1.6.5)
|
71
|
+
rack-protection (1.5.3)
|
72
|
+
rack
|
70
73
|
rack-test (0.6.3)
|
71
74
|
rack (>= 1.0)
|
72
75
|
rails (4.2.8)
|
@@ -94,6 +97,7 @@ GEM
|
|
94
97
|
rake (>= 0.8.7)
|
95
98
|
thor (>= 0.18.1, < 2.0)
|
96
99
|
rake (12.0.0)
|
100
|
+
redis (3.3.3)
|
97
101
|
request_store (1.3.2)
|
98
102
|
rspec (3.5.0)
|
99
103
|
rspec-core (~> 3.5.0)
|
@@ -116,6 +120,11 @@ GEM
|
|
116
120
|
rspec-mocks (~> 3.5.0)
|
117
121
|
rspec-support (~> 3.5.0)
|
118
122
|
rspec-support (3.5.0)
|
123
|
+
sidekiq (4.2.10)
|
124
|
+
concurrent-ruby (~> 1.0)
|
125
|
+
connection_pool (~> 2.2, >= 2.2.0)
|
126
|
+
rack-protection (>= 1.5.0)
|
127
|
+
redis (~> 3.2, >= 3.2.1)
|
119
128
|
sprockets (3.7.1)
|
120
129
|
concurrent-ruby (~> 1.0)
|
121
130
|
rack (> 1, < 3)
|
@@ -139,7 +148,8 @@ DEPENDENCIES
|
|
139
148
|
rake
|
140
149
|
rspec (>= 3.0)
|
141
150
|
rspec-rails
|
151
|
+
sidekiq
|
142
152
|
thor
|
143
153
|
|
144
154
|
BUNDLED WITH
|
145
|
-
1.
|
155
|
+
1.15.1
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
|
-
remote:
|
2
|
+
remote: ..
|
3
3
|
specs:
|
4
|
-
activerecord-multi-tenant (0.
|
4
|
+
activerecord-multi-tenant (0.7.0)
|
5
5
|
rails (>= 3.1)
|
6
6
|
request_store (>= 1.0.5)
|
7
7
|
|
@@ -52,6 +52,7 @@ GEM
|
|
52
52
|
arel (7.1.4)
|
53
53
|
builder (3.2.3)
|
54
54
|
concurrent-ruby (1.0.5)
|
55
|
+
connection_pool (2.2.1)
|
55
56
|
diff-lcs (1.3)
|
56
57
|
erubis (2.7.0)
|
57
58
|
globalid (0.3.7)
|
@@ -72,6 +73,8 @@ GEM
|
|
72
73
|
mini_portile2 (~> 2.1.0)
|
73
74
|
pg (0.20.0)
|
74
75
|
rack (2.0.1)
|
76
|
+
rack-protection (1.5.3)
|
77
|
+
rack
|
75
78
|
rack-test (0.6.3)
|
76
79
|
rack (>= 1.0)
|
77
80
|
rails (5.0.1)
|
@@ -98,6 +101,7 @@ GEM
|
|
98
101
|
rake (>= 0.8.7)
|
99
102
|
thor (>= 0.18.1, < 2.0)
|
100
103
|
rake (12.0.0)
|
104
|
+
redis (3.3.3)
|
101
105
|
request_store (1.3.2)
|
102
106
|
rspec (3.5.0)
|
103
107
|
rspec-core (~> 3.5.0)
|
@@ -120,6 +124,11 @@ GEM
|
|
120
124
|
rspec-mocks (~> 3.5.0)
|
121
125
|
rspec-support (~> 3.5.0)
|
122
126
|
rspec-support (3.5.0)
|
127
|
+
sidekiq (4.2.10)
|
128
|
+
concurrent-ruby (~> 1.0)
|
129
|
+
connection_pool (~> 2.2, >= 2.2.0)
|
130
|
+
rack-protection (>= 1.5.0)
|
131
|
+
redis (~> 3.2, >= 3.2.1)
|
123
132
|
sprockets (3.7.1)
|
124
133
|
concurrent-ruby (~> 1.0)
|
125
134
|
rack (> 1, < 3)
|
@@ -146,7 +155,8 @@ DEPENDENCIES
|
|
146
155
|
rake
|
147
156
|
rspec (>= 3.0)
|
148
157
|
rspec-rails
|
158
|
+
sidekiq
|
149
159
|
thor
|
150
160
|
|
151
161
|
BUNDLED WITH
|
152
|
-
1.
|
162
|
+
1.15.1
|
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
|
-
remote:
|
2
|
+
remote: ..
|
3
3
|
specs:
|
4
|
-
activerecord-multi-tenant (0.
|
4
|
+
activerecord-multi-tenant (0.7.0)
|
5
5
|
rails (>= 3.1)
|
6
6
|
request_store (>= 1.0.5)
|
7
7
|
|
@@ -52,6 +52,7 @@ GEM
|
|
52
52
|
arel (8.0.0)
|
53
53
|
builder (3.2.3)
|
54
54
|
concurrent-ruby (1.0.5)
|
55
|
+
connection_pool (2.2.1)
|
55
56
|
diff-lcs (1.3)
|
56
57
|
erubi (1.6.0)
|
57
58
|
globalid (0.4.0)
|
@@ -72,6 +73,8 @@ GEM
|
|
72
73
|
mini_portile2 (~> 2.1.0)
|
73
74
|
pg (0.20.0)
|
74
75
|
rack (2.0.1)
|
76
|
+
rack-protection (1.5.3)
|
77
|
+
rack
|
75
78
|
rack-test (0.6.3)
|
76
79
|
rack (>= 1.0)
|
77
80
|
rails (5.1.0)
|
@@ -98,6 +101,7 @@ GEM
|
|
98
101
|
rake (>= 0.8.7)
|
99
102
|
thor (>= 0.18.1, < 2.0)
|
100
103
|
rake (12.0.0)
|
104
|
+
redis (3.3.3)
|
101
105
|
request_store (1.3.2)
|
102
106
|
rspec (3.6.0)
|
103
107
|
rspec-core (~> 3.6.0)
|
@@ -120,6 +124,11 @@ GEM
|
|
120
124
|
rspec-mocks (~> 3.6.0)
|
121
125
|
rspec-support (~> 3.6.0)
|
122
126
|
rspec-support (3.6.0)
|
127
|
+
sidekiq (4.2.10)
|
128
|
+
concurrent-ruby (~> 1.0)
|
129
|
+
connection_pool (~> 2.2, >= 2.2.0)
|
130
|
+
rack-protection (>= 1.5.0)
|
131
|
+
redis (~> 3.2, >= 3.2.1)
|
123
132
|
sprockets (3.7.1)
|
124
133
|
concurrent-ruby (~> 1.0)
|
125
134
|
rack (> 1, < 3)
|
@@ -146,7 +155,8 @@ DEPENDENCIES
|
|
146
155
|
rake
|
147
156
|
rspec (>= 3.0)
|
148
157
|
rspec-rails
|
158
|
+
sidekiq
|
149
159
|
thor
|
150
160
|
|
151
161
|
BUNDLED WITH
|
152
|
-
1.
|
162
|
+
1.15.1
|
@@ -15,7 +15,7 @@ module MultiTenant
|
|
15
15
|
FOR t IN SELECT schemaname, tablename FROM pg_tables WHERE schemaname = 'public' AND tablename NOT IN (%s) LOOP
|
16
16
|
EXECUTE 'SELECT EXISTS (SELECT * from pg_class c WHERE c.relkind = ''S'' AND c.relname=''' || t.tablename || '_id_seq'')' into seq_exists;
|
17
17
|
IF seq_exists THEN
|
18
|
-
EXECUTE 'SELECT
|
18
|
+
EXECUTE 'SELECT is_called FROM ' || t.tablename || '_id_seq' INTO needs_truncate;
|
19
19
|
ELSE
|
20
20
|
needs_truncate := true;
|
21
21
|
END IF;
|
@@ -24,6 +24,8 @@ module MultiTenant
|
|
24
24
|
|
25
25
|
def citus_version
|
26
26
|
execute("SELECT extversion FROM pg_extension WHERE extname = 'citus'").getvalue(0,0).try(:split, '-').try(:first)
|
27
|
+
rescue ArgumentError => e
|
28
|
+
raise unless e.message == "invalid tuple number 0"
|
27
29
|
end
|
28
30
|
end
|
29
31
|
end
|
@@ -32,16 +32,21 @@ module MultiTenant
|
|
32
32
|
@primary_key = DEFAULT_ID_FIELD
|
33
33
|
end
|
34
34
|
end
|
35
|
+
|
36
|
+
def inherited(subclass)
|
37
|
+
super
|
38
|
+
MultiTenant.register_multi_tenant_model(subclass.table_name, subclass) if subclass.table_name
|
39
|
+
end
|
35
40
|
end
|
36
41
|
|
37
|
-
MultiTenant.register_multi_tenant_model(table_name, self)
|
42
|
+
MultiTenant.register_multi_tenant_model(table_name, self) if table_name
|
38
43
|
|
39
44
|
@partition_key = options[:partition_key] || MultiTenant.partition_key(tenant_name)
|
40
45
|
partition_key = @partition_key
|
41
46
|
|
42
47
|
# Create an implicit belongs_to association only if tenant class exists
|
43
48
|
if MultiTenant.tenant_klass_defined?(tenant_name)
|
44
|
-
belongs_to tenant_name, options.slice(:class_name, :inverse_of).merge(foreign_key: partition_key)
|
49
|
+
belongs_to tenant_name, options.slice(:class_name, :inverse_of).merge(foreign_key: options[:partition_key])
|
45
50
|
end
|
46
51
|
|
47
52
|
# New instances should have the tenant set
|
@@ -66,7 +71,7 @@ module MultiTenant
|
|
66
71
|
end
|
67
72
|
|
68
73
|
define_method "#{tenant_name}" do
|
69
|
-
if !MultiTenant.current_tenant_is_id? && MultiTenant.current_tenant_id && public_send(partition_key) == MultiTenant.current_tenant_id
|
74
|
+
if !association(tenant_name.to_sym).loaded? && !MultiTenant.current_tenant_is_id? && MultiTenant.current_tenant_id && public_send(partition_key) == MultiTenant.current_tenant_id
|
70
75
|
return MultiTenant.current_tenant
|
71
76
|
else
|
72
77
|
super()
|
@@ -4,48 +4,114 @@ module MultiTenant
|
|
4
4
|
class ArelTenantVisitor < Arel::Visitors::DepthFirst
|
5
5
|
def initialize(arel)
|
6
6
|
super(Proc.new {})
|
7
|
-
@tenant_relations =
|
7
|
+
@tenant_relations = {}
|
8
|
+
@existing_tenant_relations = {}
|
9
|
+
@outer_joins_by_table_name = {}
|
10
|
+
@statement_node_id = nil
|
8
11
|
|
9
12
|
accept(arel.ast)
|
10
13
|
end
|
11
14
|
|
12
15
|
def tenant_relations
|
13
|
-
@tenant_relations
|
16
|
+
@tenant_relations
|
14
17
|
end
|
15
18
|
|
16
|
-
def
|
17
|
-
@
|
19
|
+
def existing_tenant_relations
|
20
|
+
@existing_tenant_relations
|
18
21
|
end
|
19
22
|
|
20
|
-
def
|
21
|
-
@
|
23
|
+
def outer_joins_by_table_name
|
24
|
+
@outer_joins_by_table_name
|
22
25
|
end
|
23
26
|
|
27
|
+
def visit_Arel_Table(o, _collector = nil)
|
28
|
+
@tenant_relations[@statement_node_id] ||= []
|
29
|
+
@tenant_relations[@statement_node_id] << o if tenant_relation?(o.table_name)
|
30
|
+
end
|
31
|
+
alias :visit_Arel_Nodes_TableAlias :visit_Arel_Table
|
32
|
+
|
33
|
+
def visit_Arel_Nodes_SelectStatement(o, _collector = nil)
|
34
|
+
@statement_node_id = o.object_id
|
35
|
+
visit o.cores
|
36
|
+
visit o.orders
|
37
|
+
visit o.limit
|
38
|
+
visit o.lock
|
39
|
+
visit o.offset
|
40
|
+
end
|
41
|
+
|
42
|
+
def visit_Arel_Nodes_Equality(o, _collector = nil)
|
43
|
+
if o.left.is_a?(Arel::Attributes::Attribute)
|
44
|
+
table_name = o.left.relation.table_name
|
45
|
+
model = MultiTenant.multi_tenant_model_for_table(table_name)
|
46
|
+
@existing_tenant_relations[@statement_node_id] ||= []
|
47
|
+
@existing_tenant_relations[@statement_node_id] << o.left.relation if model.present? && o.left.name == model.partition_key
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def visit_Arel_Nodes_OuterJoin(o, collector = nil)
|
52
|
+
if o.left.is_a?(Arel::Nodes::TableAlias) || o.left.is_a?(Arel::Table)
|
53
|
+
@outer_joins_by_table_name[@statement_node_id] ||= {}
|
54
|
+
@outer_joins_by_table_name[@statement_node_id][o.left.name] = o
|
55
|
+
end
|
56
|
+
visit o.left
|
57
|
+
visit o.right
|
58
|
+
end
|
59
|
+
alias :visit_Arel_Nodes_FullOuterJoin :visit_Arel_Nodes_OuterJoin
|
60
|
+
alias :visit_Arel_Nodes_RightOuterJoin :visit_Arel_Nodes_OuterJoin
|
61
|
+
|
24
62
|
private
|
25
63
|
|
26
|
-
def tenant_relation?(
|
27
|
-
MultiTenant.multi_tenant_model_for_table(
|
64
|
+
def tenant_relation?(table_name)
|
65
|
+
MultiTenant.multi_tenant_model_for_table(table_name).present?
|
28
66
|
end
|
29
67
|
end
|
30
68
|
end
|
31
69
|
|
70
|
+
require 'active_record/relation'
|
32
71
|
module ActiveRecord
|
33
|
-
module
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
72
|
+
module QueryMethods
|
73
|
+
alias :build_arel_orig :build_arel
|
74
|
+
def build_arel
|
75
|
+
arel = build_arel_orig
|
76
|
+
|
77
|
+
if MultiTenant.current_tenant_id && !MultiTenant.with_write_only_mode_enabled?
|
78
|
+
visitor = MultiTenant::ArelTenantVisitor.new(arel)
|
79
|
+
visitor.tenant_relations.each do |statement_node_id, relations|
|
80
|
+
# Process every level of the statement separately, so we don't mix subselects
|
81
|
+
known_relations = visitor.existing_tenant_relations[statement_node_id] || []
|
82
|
+
outer_joins_by_table_name = visitor.outer_joins_by_table_name[statement_node_id] || {}
|
83
|
+
|
84
|
+
relations.each do |relation|
|
42
85
|
model = MultiTenant.multi_tenant_model_for_table(relation.table_name)
|
43
|
-
next
|
44
|
-
|
86
|
+
next unless model.present?
|
87
|
+
next if known_relations.map(&:name).include?(relation.name)
|
88
|
+
|
89
|
+
tenant_relation = known_relations.reject { |r| outer_joins_by_table_name.key?(r.name) }.first
|
90
|
+
tenant_value = if tenant_relation.present?
|
91
|
+
known_model = MultiTenant.multi_tenant_model_for_table(tenant_relation.table_name)
|
92
|
+
tenant_relation[known_model.partition_key]
|
93
|
+
else
|
94
|
+
MultiTenant.current_tenant_id
|
95
|
+
end
|
96
|
+
|
97
|
+
known_relations << relation
|
98
|
+
|
99
|
+
outer_join = outer_joins_by_table_name[relation.name]
|
100
|
+
if outer_join
|
101
|
+
outer_join.right.expr = Arel::Nodes::And.new([outer_join.right.expr, relation[model.partition_key].eq(tenant_value)])
|
102
|
+
else
|
103
|
+
ctx = arel.ast.cores.last
|
104
|
+
if ctx.wheres.size == 1
|
105
|
+
ctx.wheres = [Arel::Nodes::And.new([ctx.wheres.first, relation[model.partition_key].eq(tenant_value)])]
|
106
|
+
else
|
107
|
+
arel = arel.where(relation[model.partition_key].eq(tenant_value))
|
108
|
+
end
|
109
|
+
end
|
45
110
|
end
|
46
111
|
end
|
47
|
-
to_sql_orig(arel, binds)
|
48
112
|
end
|
113
|
+
|
114
|
+
arel
|
49
115
|
end
|
50
116
|
end
|
51
117
|
end
|
@@ -18,8 +18,7 @@ module Sidekiq::Middleware::MultiTenant
|
|
18
18
|
class Server
|
19
19
|
def call(worker_class, msg, queue)
|
20
20
|
if msg.has_key?('multi_tenant')
|
21
|
-
|
22
|
-
MultiTenant.with(tenant) do
|
21
|
+
MultiTenant.with(msg['multi_tenant']['id']) do
|
23
22
|
yield
|
24
23
|
end
|
25
24
|
else
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MultiTenant::FastTruncate do
|
4
|
+
before(:each) do
|
5
|
+
MultiTenant::FastTruncate.run
|
6
|
+
end
|
7
|
+
|
8
|
+
it "truncates tables that have exactly one row inserted" do
|
9
|
+
Account.create! name: 'foo'
|
10
|
+
expect {
|
11
|
+
MultiTenant::FastTruncate.run
|
12
|
+
}.to change { Account.count }.from(1).to(0)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "truncates tables that have more than one row inserted" do
|
16
|
+
Account.create! name: 'foo'
|
17
|
+
Account.create! name: 'bar'
|
18
|
+
|
19
|
+
expect {
|
20
|
+
MultiTenant::FastTruncate.run
|
21
|
+
}.to change { Account.count }.from(2).to(0)
|
22
|
+
end
|
23
|
+
end
|
@@ -150,8 +150,8 @@ describe MultiTenant do
|
|
150
150
|
let(:account) { Account.create!(name: 'foo') }
|
151
151
|
let(:project) { Project.create!(name: 'project', account: account) }
|
152
152
|
let(:manager) { Manager.create!(name: 'manager', account: account, project: project) }
|
153
|
-
let(:task) { project.tasks.create!(name: 'task') }
|
154
|
-
let(:sub_task) { task.sub_tasks.create!(name: 'sub task') }
|
153
|
+
let(:task) { project.tasks.create!(name: 'eager loading test task') }
|
154
|
+
let(:sub_task) { task.sub_tasks.create!(name: 'eager loading test sub task') }
|
155
155
|
|
156
156
|
it 'handles table aliases through joins' do
|
157
157
|
MultiTenant.with(account) do
|
@@ -162,11 +162,22 @@ describe MultiTenant do
|
|
162
162
|
end
|
163
163
|
end
|
164
164
|
|
165
|
-
describe '
|
165
|
+
describe 'sub selects' do
|
166
166
|
let(:account) { Account.create!(name: 'foo') }
|
167
167
|
let(:project) { Project.create!(name: 'project', account: account) }
|
168
|
-
|
169
|
-
|
168
|
+
|
169
|
+
it 'rewrites sub-selects correctly' do
|
170
|
+
MultiTenant.with(account) do
|
171
|
+
expect(Project.where(id: Project.where(id: project.id)).where(id: Project.where(id: project.id)).first).to eq project
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe 'STI Subclass of Multi Tenant Model' do
|
177
|
+
let(:account) { Account.create!(name: 'foo') }
|
178
|
+
let(:project) { Project.create!(name: 'project', account: account) }
|
179
|
+
let(:task) { project.tasks.create!(name: 'subclass test task') }
|
180
|
+
let(:sti_task) { StiSubTask.create!(task: task, name: 'subclass test sub task') }
|
170
181
|
|
171
182
|
it 'has partition key' do
|
172
183
|
expect(StiSubTask.partition_key).to eq 'account_id'
|
@@ -177,21 +188,43 @@ describe MultiTenant do
|
|
177
188
|
expect(StiSubTask.primary_key).to eq 'id'
|
178
189
|
end
|
179
190
|
|
180
|
-
it 'handles
|
191
|
+
it 'handles associations' do
|
181
192
|
MultiTenant.with(account) do
|
182
193
|
expect(sti_task.project).to eq project
|
194
|
+
expect(project.sub_tasks.to_a).to eq [sti_task]
|
183
195
|
end
|
184
196
|
end
|
197
|
+
end
|
185
198
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
199
|
+
describe 'non-STI Subclass of abstract Multi Tenant Model' do
|
200
|
+
let(:tenant_id_1) { 42 }
|
201
|
+
let(:tenant_id_2) { 314158 }
|
202
|
+
let(:name) { 'fooname' }
|
203
|
+
let(:subclass_task_1) do
|
204
|
+
MultiTenant.with(tenant_id_1) { SubclassTask.create! name: name }
|
205
|
+
end
|
206
|
+
let(:subclass_task_2) do
|
207
|
+
MultiTenant.with(tenant_id_2) { SubclassTask.create! name: name }
|
190
208
|
end
|
191
209
|
|
192
|
-
|
193
|
-
|
194
|
-
|
210
|
+
before do
|
211
|
+
subclass_task_1
|
212
|
+
subclass_task_2
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'injects tenant_id on create' do
|
216
|
+
expect(subclass_task_1.non_model_id).to be tenant_id_1
|
217
|
+
expect(subclass_task_2.non_model_id).to be tenant_id_2
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'rewrites query' do
|
221
|
+
MultiTenant.with(tenant_id_1) do
|
222
|
+
expect(SubclassTask.where(name: name).count).to eq 1
|
223
|
+
expect(SubclassTask.where(name: name).first).to eq subclass_task_1
|
224
|
+
end
|
225
|
+
MultiTenant.with(tenant_id_2) do
|
226
|
+
expect(SubclassTask.where(name: name).count).to eq 1
|
227
|
+
expect(SubclassTask.where(name: name).first).to eq subclass_task_2
|
195
228
|
end
|
196
229
|
end
|
197
230
|
end
|
@@ -253,4 +286,20 @@ describe MultiTenant do
|
|
253
286
|
end
|
254
287
|
end
|
255
288
|
end
|
289
|
+
|
290
|
+
if ActiveRecord::VERSION::MAJOR > 4 || (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR > 0)
|
291
|
+
# Reflection
|
292
|
+
describe 'with unsaved association' do
|
293
|
+
before do
|
294
|
+
@account = Account.create!(name: 'reflection tenant')
|
295
|
+
@manager = Manager.new(account: @account)
|
296
|
+
MultiTenant.current_tenant = @account
|
297
|
+
@account.update! name: 'reflection tenant update'
|
298
|
+
end
|
299
|
+
|
300
|
+
it 'persists the reflected association' do
|
301
|
+
expect(@manager.persisted?).to eq(true)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
256
305
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'sidekiq/client'
|
3
|
+
require 'activerecord-multi-tenant/sidekiq'
|
4
|
+
|
5
|
+
describe MultiTenant, 'Sidekiq' do
|
6
|
+
let(:server) { Sidekiq::Middleware::MultiTenant::Server.new }
|
7
|
+
|
8
|
+
describe 'server middleware' do
|
9
|
+
it 'sets the multitenant context when provided in message' do
|
10
|
+
tenant_id = 1234
|
11
|
+
server.call(double, {'bogus' => 'message',
|
12
|
+
'multi_tenant' => { 'class' => MultiTenant.current_tenant_class, 'id' => tenant_id}},
|
13
|
+
'bogus_queue') do
|
14
|
+
expect(MultiTenant.current_tenant).to eq(tenant_id)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'does not set the multitenant context when no tenant provided' do
|
19
|
+
server.call(double, {'bogus' => 'message'}, 'bogus_queue') do
|
20
|
+
expect(MultiTenant.current_tenant).to be_nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/schema.rb
CHANGED
@@ -61,6 +61,11 @@ ARGV.grep(/\w+_spec\.rb/).empty? && ActiveRecord::Schema.define(version: 1) do
|
|
61
61
|
t.column :name, :string
|
62
62
|
end
|
63
63
|
|
64
|
+
create_table :subclass_tasks, force: true, partition_key: :non_model_id do |t|
|
65
|
+
t.column :non_model_id, :integer
|
66
|
+
t.column :name, :string
|
67
|
+
end
|
68
|
+
|
64
69
|
create_distributed_table :accounts, :id
|
65
70
|
create_distributed_table :projects, :account_id
|
66
71
|
create_distributed_table :managers, :account_id
|
@@ -70,11 +75,13 @@ ARGV.grep(/\w+_spec\.rb/).empty? && ActiveRecord::Schema.define(version: 1) do
|
|
70
75
|
create_distributed_table :custom_partition_key_tasks, :accountID
|
71
76
|
create_distributed_table :comments, :account_id
|
72
77
|
create_distributed_table :partition_key_not_model_tasks, :non_model_id
|
78
|
+
create_distributed_table :subclass_tasks, :non_model_id
|
73
79
|
end
|
74
80
|
|
75
81
|
class Account < ActiveRecord::Base
|
76
82
|
multi_tenant :account
|
77
83
|
has_many :projects
|
84
|
+
has_one :manager, inverse_of: :account
|
78
85
|
end
|
79
86
|
|
80
87
|
class Project < ActiveRecord::Base
|
@@ -137,6 +144,14 @@ class PartitionKeyNotModelTask < ActiveRecord::Base
|
|
137
144
|
multi_tenant :non_model
|
138
145
|
end
|
139
146
|
|
147
|
+
class AbstractTask < ActiveRecord::Base
|
148
|
+
self.abstract_class = true
|
149
|
+
multi_tenant :non_model
|
150
|
+
end
|
151
|
+
|
152
|
+
class SubclassTask < AbstractTask
|
153
|
+
end
|
154
|
+
|
140
155
|
class Comment < ActiveRecord::Base
|
141
156
|
multi_tenant :account
|
142
157
|
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.
|
4
|
+
version: 0.7.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-
|
11
|
+
date: 2017-07-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: request_store
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: sidekiq
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: thor
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -152,10 +166,12 @@ files:
|
|
152
166
|
- lib/activerecord-multi-tenant/version.rb
|
153
167
|
- lib/activerecord-multi-tenant/with_lock.rb
|
154
168
|
- spec/activerecord-multi-tenant/controller_extensions_spec.rb
|
169
|
+
- spec/activerecord-multi-tenant/fast_truncate_spec.rb
|
155
170
|
- spec/activerecord-multi-tenant/model_extensions_spec.rb
|
156
171
|
- spec/activerecord-multi-tenant/record_callback_spec.rb
|
157
172
|
- spec/activerecord-multi-tenant/record_finding_spec.rb
|
158
173
|
- spec/activerecord-multi-tenant/record_modifications_spec.rb
|
174
|
+
- spec/activerecord-multi-tenant/sidekiq_spec.rb
|
159
175
|
- spec/database.yml
|
160
176
|
- spec/schema.rb
|
161
177
|
- spec/spec_helper.rb
|