motel-activerecord 2.1.0 → 3.0.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 +4 -4
- data/README.md +30 -47
- data/VERSION +1 -1
- data/lib/motel-activerecord.rb +0 -1
- data/lib/motel/active_record.rb +0 -2
- data/lib/motel/active_record/connection_handler.rb +10 -4
- data/lib/motel/active_record/railties/databases.rake +38 -0
- data/lib/motel/manager.rb +9 -22
- data/lib/motel/railtie.rb +8 -15
- data/spec/lib/motel/active_record/connection_handler.rb +51 -22
- data/spec/lib/motel/manager_spec.rb +11 -16
- data/spec/tmp/tenants.sqlite3 +0 -0
- metadata +3 -7
- data/lib/motel/active_record/migration.rb +0 -36
- data/lib/motel/active_record/query_cache.rb +0 -73
- data/lib/motel/lobby.rb +0 -39
- data/spec/lib/motel/lobby_spec.rb +0 -133
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bbdd40d34d7c12ab8b85ebf22ad4c05fb9d68ec7
|
4
|
+
data.tar.gz: 42ff7e4c146a83c443e70fadc69201ddb5c756d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd1193af26b506bc7734695b2716a9bc4f448546dd4ffd49b89d471603687765d5797b102f22f4001cc83ee9e5a82a193e97f90f2cffddad2495305cb240a163
|
7
|
+
data.tar.gz: e35b6efaee61dc09687d5cdb3e3fe29361ea773076f5f97f5b8b5183a89db497c440b8bfc74c76948fc0a59d5d7a9d833d6f429d9ce2ae060e0c885d696796b7
|
data/README.md
CHANGED
@@ -8,6 +8,7 @@ connections to multiple databases, one for each tenant.
|
|
8
8
|
|
9
9
|
* Adds multi-tenant functionality to ActiveRecord.
|
10
10
|
* Multiple databases, one for each tenant.
|
11
|
+
* Databases of tenants may be in different locations.
|
11
12
|
* Tenant connection details are stored keying them by the name on a database or redis server.
|
12
13
|
* Use with or without Rails.
|
13
14
|
|
@@ -126,29 +127,21 @@ specific tenant.
|
|
126
127
|
$ TENANT=foo rake db:migrate
|
127
128
|
```
|
128
129
|
|
129
|
-
|
130
|
-
|
131
|
-
You can assign a default tenant if the current tenant is null:
|
130
|
+
To create the database of all tenants.
|
132
131
|
|
133
132
|
```ruby
|
134
|
-
|
133
|
+
rake db:create:all
|
135
134
|
```
|
136
135
|
|
137
|
-
|
138
|
-
specify a criteria to identify the tenant providing a regex as a
|
139
|
-
string. Example, to get the tenant `foo` from the follow url
|
140
|
-
`http://www.example.com/foo/index` you should write:
|
136
|
+
To drop the database of all tenants.
|
141
137
|
|
142
138
|
```ruby
|
143
|
-
|
139
|
+
rake db:drop:all
|
144
140
|
```
|
145
141
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
```ruby
|
150
|
-
config.motel.disable_middleware = true
|
151
|
-
```
|
142
|
+
(Note: Is necessary to establish a **default tenant** because the
|
143
|
+
middlewares of ActiveRecord require a connection to function
|
144
|
+
properly and shared pages between tenants can be viewed.)
|
152
145
|
|
153
146
|
## Use without Rails
|
154
147
|
|
@@ -169,37 +162,32 @@ Motel::Manager.tenants_source_configurations({
|
|
169
162
|
|
170
163
|
## Switching tenants
|
171
164
|
|
172
|
-
|
173
|
-
through the Lobby middleware, otherwise you must set the current
|
174
|
-
tenant:
|
165
|
+
To switch between tenants:
|
175
166
|
|
176
167
|
```ruby
|
177
|
-
Motel::Manager.
|
168
|
+
Motel::Manager.switch_tenant("foo")
|
178
169
|
```
|
179
170
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
```ruby
|
186
|
-
ENV["TENANT"] || Motel::Manager.current_tenant || Motel::Manager.default_tenant
|
187
|
-
```
|
171
|
+
To determine the tenant of the connection to retrieve a fallback is
|
172
|
+
performed through the variables that are used to set the tenant in
|
173
|
+
the following order: environment variable `ENV['TENANT']`,
|
174
|
+
tenant switched `Motel::Manager.switch_tenant()` and default tenant
|
175
|
+
`Motel::Manager.default_tenant`.
|
188
176
|
|
189
177
|
Usage example:
|
190
178
|
|
191
179
|
```ruby
|
192
|
-
Motel::Manager.
|
180
|
+
Motel::Manager.switch_tenant("foo")
|
193
181
|
|
194
182
|
FooBar.create(name: "Foo")
|
195
183
|
# => #<FooBar id: 1, name: "Foo">
|
196
184
|
|
197
|
-
Motel::Manager.
|
185
|
+
Motel::Manager.switch_tenant("bar")
|
198
186
|
|
199
187
|
FooBar.all
|
200
188
|
# => #<ActiveRecord::Relation []>
|
201
189
|
|
202
|
-
Motel::Manager.
|
190
|
+
Motel::Manager.switch_tenant("foo")
|
203
191
|
|
204
192
|
FooBar.all
|
205
193
|
# => #<ActiveRecord::Relation [#<FooBar id: 1, name: "Foo">]>
|
@@ -207,74 +195,69 @@ Usage example:
|
|
207
195
|
|
208
196
|
# Available methods
|
209
197
|
|
210
|
-
|
198
|
+
Sets a tenats source configurations
|
211
199
|
|
212
200
|
```ruby
|
213
201
|
Motel::Manager.tenants_source_configurations(config)
|
214
202
|
```
|
215
203
|
|
216
|
-
|
204
|
+
Switches the tenant
|
217
205
|
|
218
206
|
```ruby
|
219
|
-
Motel::Manager.
|
207
|
+
Motel::Manager.switch_tenant(name)
|
220
208
|
```
|
221
209
|
|
222
|
-
|
210
|
+
Sets a default tenant
|
223
211
|
|
224
212
|
```ruby
|
225
213
|
Motel::Manager.default_tenant
|
226
214
|
```
|
227
215
|
|
228
|
-
|
216
|
+
Retrieves a current tenant
|
229
217
|
|
230
218
|
```ruby
|
231
219
|
Motel::Manager.current_tenant
|
232
220
|
```
|
233
221
|
|
234
|
-
|
222
|
+
Retrieves the connection details of all tenants
|
235
223
|
|
236
224
|
```ruby
|
237
225
|
Motel::Manager.tenants
|
238
226
|
```
|
239
227
|
|
240
|
-
|
228
|
+
Retrieves a tenant
|
241
229
|
|
242
230
|
```ruby
|
243
231
|
Motel::Manager.tenant(name)
|
244
232
|
```
|
245
233
|
|
246
|
-
|
234
|
+
Determines if a tenant exists
|
247
235
|
|
248
236
|
```ruby
|
249
237
|
Motel::Manager.tenant?(name)
|
250
238
|
```
|
251
239
|
|
252
|
-
|
240
|
+
Adds tenant
|
253
241
|
|
254
242
|
```ruby
|
255
243
|
Motel::Manager.add_tenant(name, spec)
|
256
244
|
```
|
257
245
|
|
258
|
-
|
246
|
+
Updates tenant
|
259
247
|
|
260
248
|
```ruby
|
261
249
|
Motel::Manager.update_tenant(name, spec)
|
262
250
|
```
|
263
251
|
|
264
|
-
|
252
|
+
Deletes tenant
|
265
253
|
|
266
254
|
```ruby
|
267
255
|
Motel::Manager.delete_tenant(name)
|
268
256
|
```
|
269
257
|
|
270
|
-
|
258
|
+
Retrieves the names of the tenants of active connections
|
271
259
|
|
272
260
|
```ruby
|
273
261
|
Motel::Manager.active_tenants
|
274
262
|
```
|
275
263
|
|
276
|
-
Determine the tenant to use for the connection
|
277
|
-
|
278
|
-
```ruby
|
279
|
-
Motel::Manager.determines_tenant
|
280
|
-
```
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
3.0.0
|
data/lib/motel-activerecord.rb
CHANGED
data/lib/motel/active_record.rb
CHANGED
@@ -16,9 +16,15 @@ module Motel
|
|
16
16
|
module ClassMethods
|
17
17
|
|
18
18
|
def establish_connection(config)
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
case config
|
20
|
+
when String, Symbol
|
21
|
+
tenant_name = config.to_s
|
22
|
+
spec = nil
|
23
|
+
else
|
24
|
+
tenant_name = current_tenant
|
25
|
+
resolver = Motel::ConnectionAdapters::ConnectionSpecification::Resolver.new
|
26
|
+
spec = resolver.spec(config)
|
27
|
+
end
|
22
28
|
|
23
29
|
connection_handler.establish_connection tenant_name, spec
|
24
30
|
end
|
@@ -44,7 +50,7 @@ module Motel
|
|
44
50
|
end
|
45
51
|
|
46
52
|
def current_tenant
|
47
|
-
Motel::Manager.
|
53
|
+
Motel::Manager.current_tenant or raise Motel::NoCurrentTenantError
|
48
54
|
end
|
49
55
|
|
50
56
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
db_namespace = namespace :db do
|
4
|
+
|
5
|
+
Rake::Task['db:create:all'].clear
|
6
|
+
namespace :create do
|
7
|
+
task :all => :load_config do
|
8
|
+
Motel::Manager.tenants.each do |tenant_name, config|
|
9
|
+
Motel::Manager.switch_tenant(tenant_name)
|
10
|
+
ActiveRecord::Tasks::DatabaseTasks.create config
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Rake::Task['db:drop:all'].clear
|
16
|
+
namespace :drop do
|
17
|
+
task :all => :load_config do
|
18
|
+
Motel::Manager.tenants.each do |tenant_name, config|
|
19
|
+
Motel::Manager.switch_tenant(tenant_name)
|
20
|
+
ActiveRecord::Tasks::DatabaseTasks.drop config
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
if Rake::Task.task_defined?('db:purge:all')
|
26
|
+
Rake::Task['db:purge:all'].clear
|
27
|
+
namespace :purge do
|
28
|
+
task :all => :load_config do
|
29
|
+
Motel::Manager.tenants.each do |tenant_name, config|
|
30
|
+
Motel::Manager.switch_tenant(tenant_name)
|
31
|
+
ActiveRecord::Tasks::DatabaseTasks.purge config
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
data/lib/motel/manager.rb
CHANGED
@@ -5,7 +5,6 @@ require 'active_record'
|
|
5
5
|
module Motel
|
6
6
|
module Manager
|
7
7
|
|
8
|
-
mattr_accessor :admission_criteria
|
9
8
|
mattr_accessor :default_tenant
|
10
9
|
|
11
10
|
class << self
|
@@ -28,7 +27,7 @@ module Motel
|
|
28
27
|
end
|
29
28
|
|
30
29
|
def tenant?(name)
|
31
|
-
|
30
|
+
tenants_source.tenant?(name)
|
32
31
|
end
|
33
32
|
|
34
33
|
def add_tenant(name, spec)
|
@@ -48,36 +47,24 @@ module Motel
|
|
48
47
|
!tenant?(name)
|
49
48
|
end
|
50
49
|
|
50
|
+
def switch_tenant(name)
|
51
|
+
Thread.current.thread_variable_set(:@current_tenant, name)
|
52
|
+
end
|
53
|
+
|
51
54
|
def active_tenants
|
52
55
|
::ActiveRecord::Base.connection_handler.active_tenants
|
53
56
|
end
|
54
57
|
|
55
|
-
def
|
56
|
-
ENV['TENANT'] ||
|
58
|
+
def current_tenant
|
59
|
+
ENV['TENANT'] ||
|
60
|
+
Thread.current.thread_variable_get(:@current_tenant) ||
|
61
|
+
default_tenant
|
57
62
|
end
|
58
63
|
|
59
64
|
def tenants_source
|
60
65
|
::ActiveRecord::Base.connection_handler.tenants_source
|
61
66
|
end
|
62
67
|
|
63
|
-
def current_tenant=(tenant)
|
64
|
-
Thread.current.thread_variable_set(:@current_tenant, tenant)
|
65
|
-
end
|
66
|
-
|
67
|
-
def current_tenant
|
68
|
-
Thread.current.thread_variable_get(:@current_tenant)
|
69
|
-
end
|
70
|
-
|
71
|
-
def nonexistent_tenant_page=(path_page)
|
72
|
-
warn "[DEPRECATION] `nonexistent_tenant_page` is deprecated. The page is manage for ActionDispatch::DebugExceptions middleware."
|
73
|
-
@nonexistent_tenant_page = path_page
|
74
|
-
end
|
75
|
-
|
76
|
-
def nonexistent_tenant_page
|
77
|
-
warn "[DEPRECATION] `nonexistent_tenant_page` is deprecated. The page is manage for ActionDispatch::DebugExceptions middleware."
|
78
|
-
@nonexistent_tenant_page
|
79
|
-
end
|
80
|
-
|
81
68
|
end
|
82
69
|
|
83
70
|
end
|
data/lib/motel/railtie.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'active_support/ordered_options'
|
2
2
|
require 'motel/manager'
|
3
|
+
require 'active_record'
|
3
4
|
require 'rails'
|
5
|
+
require 'active_model/railtie'
|
4
6
|
|
5
7
|
module Motel
|
6
8
|
|
@@ -15,21 +17,21 @@ module Motel
|
|
15
17
|
)
|
16
18
|
|
17
19
|
rake_tasks do
|
20
|
+
require "active_record/base"
|
21
|
+
|
18
22
|
namespace :db do
|
19
23
|
task :load_config do
|
20
24
|
Motel::Manager.tenants_source_configurations(
|
21
25
|
Rails.application.config.motel.tenants_source_configurations
|
22
26
|
)
|
23
27
|
|
24
|
-
# Set a current tenant allow to db:create:all task establish and
|
25
|
-
# retrieve the connection
|
26
|
-
Motel::Manager.current_tenant ||= self.class
|
27
|
-
|
28
28
|
::ActiveRecord::Tasks::DatabaseTasks.database_configuration = Motel::Manager.tenants
|
29
29
|
::ActiveRecord::Base.configurations = ::ActiveRecord::Tasks::DatabaseTasks.database_configuration
|
30
|
-
::ActiveRecord::Tasks::DatabaseTasks.env = Motel::Manager.
|
30
|
+
::ActiveRecord::Tasks::DatabaseTasks.env = Motel::Manager.current_tenant
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
load "motel/active_record/railties/databases.rake"
|
33
35
|
end
|
34
36
|
|
35
37
|
::ActiveRecord::Railtie.initializers.delete_if do |i|
|
@@ -39,19 +41,10 @@ module Motel
|
|
39
41
|
initializer "motel.general_configuration" do
|
40
42
|
motel_config = Rails.application.config.motel
|
41
43
|
|
42
|
-
Motel::Manager.nonexistent_tenant_page = motel_config.nonexistent_tenant_page || 'public/404.html' # Deprecated
|
43
|
-
Motel::Manager.admission_criteria = motel_config.admission_criteria
|
44
44
|
Motel::Manager.default_tenant = motel_config.default_tenant
|
45
45
|
Motel::Manager.tenants_source_configurations(motel_config.tenants_source_configurations)
|
46
46
|
end
|
47
47
|
|
48
|
-
# Set lobby middleware before all ActiveRecord's middlewares
|
49
|
-
initializer "motel.configure_middleware" do |app|
|
50
|
-
if !Rails.application.config.motel.disable_middleware && (Rails.env != 'test')
|
51
|
-
app.config.middleware.insert_after ActionDispatch::Callbacks, Lobby
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
48
|
initializer "active_record.set_reloader_hooks" do |app|
|
56
49
|
hook = app.config.reload_classes_only_on_change ? :to_prepare : :to_cleanup
|
57
50
|
|
@@ -59,7 +52,7 @@ module Motel
|
|
59
52
|
ActionDispatch::Reloader.send(hook) do
|
60
53
|
::ActiveRecord::Base.clear_reloadable_connections!
|
61
54
|
# Clear cache of the current tenant with an active connection
|
62
|
-
if Motel::Manager.active_tenants.include?(Motel::Manager.
|
55
|
+
if Motel::Manager.active_tenants.include?(Motel::Manager.current_tenant)
|
63
56
|
::ActiveRecord::Base.clear_cache!
|
64
57
|
end
|
65
58
|
end
|
@@ -17,31 +17,60 @@ describe ::ActiveRecord::Base do
|
|
17
17
|
::ActiveRecord::Base.connection_handler.active_tenants do |tenant|
|
18
18
|
::ActiveRecord::Base.connection_handler.remove_connection(tenant)
|
19
19
|
end
|
20
|
-
Motel::Manager.
|
20
|
+
Motel::Manager.switch_tenant(nil)
|
21
|
+
ENV['TENANT'] = nil
|
21
22
|
end
|
22
23
|
|
23
24
|
describe '.establish_connection' do
|
24
25
|
|
25
|
-
context '
|
26
|
+
context 'with a connection specification' do
|
27
|
+
|
28
|
+
context 'and the environment variable of the current is established' do
|
29
|
+
|
30
|
+
before(:each) do
|
31
|
+
ENV['TENANT'] = 'foo'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'establishes a connection keyed by tenant name' do
|
35
|
+
::ActiveRecord::Base.establish_connection(FOO_SPEC)
|
36
|
+
|
37
|
+
expect(::ActiveRecord::Base.connection_handler.active_tenants).to include('foo')
|
38
|
+
end
|
26
39
|
|
27
|
-
before(:each) do
|
28
|
-
Motel::Manager.current_tenant = 'foo'
|
29
40
|
end
|
30
41
|
|
31
|
-
|
32
|
-
|
42
|
+
context 'and the environment variable of the current is not established' do
|
43
|
+
|
44
|
+
it 'establishes a connection keyed by name of the class' do
|
45
|
+
::ActiveRecord::Base.establish_connection(FOO_SPEC)
|
46
|
+
|
47
|
+
expect(::ActiveRecord::Base.connection_handler.active_tenants).to include('ActiveRecord::Base')
|
48
|
+
end
|
33
49
|
|
34
|
-
expect(::ActiveRecord::Base.connection_handler.active_tenants).to include('foo')
|
35
50
|
end
|
36
51
|
|
37
52
|
end
|
38
53
|
|
39
|
-
context '
|
54
|
+
context 'with a tenant name' do
|
55
|
+
|
56
|
+
context 'existent' do
|
57
|
+
|
58
|
+
it 'establishes a connection keyed by tenant name' do
|
59
|
+
::ActiveRecord::Base.establish_connection('foo')
|
60
|
+
|
61
|
+
expect(::ActiveRecord::Base.connection_handler.active_tenants).to include('foo')
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'nonexistent' do
|
40
67
|
|
41
|
-
|
42
|
-
|
68
|
+
it 'raises an error' do
|
69
|
+
expect{
|
70
|
+
::ActiveRecord::Base.establish_connection('baz')
|
71
|
+
}.to raise_error Motel::NonexistentTenantError
|
72
|
+
end
|
43
73
|
|
44
|
-
expect(::ActiveRecord::Base.connection_handler.active_tenants).to include('ActiveRecord::Base')
|
45
74
|
end
|
46
75
|
|
47
76
|
end
|
@@ -53,7 +82,7 @@ describe ::ActiveRecord::Base do
|
|
53
82
|
context 'current tenant established' do
|
54
83
|
|
55
84
|
it 'returns a connection pool of current tenant' do
|
56
|
-
Motel::Manager.
|
85
|
+
Motel::Manager.switch_tenant('foo')
|
57
86
|
pool = ::ActiveRecord::Base.connection_handler.establish_connection('foo')
|
58
87
|
|
59
88
|
expect(::ActiveRecord::Base.connection_pool).to eq pool
|
@@ -64,7 +93,7 @@ describe ::ActiveRecord::Base do
|
|
64
93
|
context 'current tenant not established' do
|
65
94
|
|
66
95
|
it 'rises an error' do
|
67
|
-
Motel::Manager.
|
96
|
+
Motel::Manager.switch_tenant(nil)
|
68
97
|
expect{::ActiveRecord::Base.connection_pool}.to raise_error Motel::NoCurrentTenantError
|
69
98
|
end
|
70
99
|
|
@@ -77,7 +106,7 @@ describe ::ActiveRecord::Base do
|
|
77
106
|
context 'current tenant established' do
|
78
107
|
|
79
108
|
it 'returns a connection of current tenant' do
|
80
|
-
Motel::Manager.
|
109
|
+
Motel::Manager.switch_tenant('foo')
|
81
110
|
pool = ::ActiveRecord::Base.connection_handler.establish_connection('foo')
|
82
111
|
|
83
112
|
expect(::ActiveRecord::Base.retrieve_connection).to eq pool.connection
|
@@ -88,7 +117,7 @@ describe ::ActiveRecord::Base do
|
|
88
117
|
context 'current tenant not established' do
|
89
118
|
|
90
119
|
it 'rises an error' do
|
91
|
-
Motel::Manager.
|
120
|
+
Motel::Manager.switch_tenant(nil)
|
92
121
|
expect{::ActiveRecord::Base.retrieve_connection}.to raise_error Motel::NoCurrentTenantError
|
93
122
|
end
|
94
123
|
|
@@ -105,12 +134,12 @@ describe ::ActiveRecord::Base do
|
|
105
134
|
context 'current tenant established' do
|
106
135
|
|
107
136
|
it 'returns true' do
|
108
|
-
Motel::Manager.
|
137
|
+
Motel::Manager.switch_tenant('foo')
|
109
138
|
expect(::ActiveRecord::Base.connected?).to be_truthy
|
110
139
|
end
|
111
140
|
|
112
141
|
it 'returns false' do
|
113
|
-
Motel::Manager.
|
142
|
+
Motel::Manager.switch_tenant('bar')
|
114
143
|
expect(::ActiveRecord::Base.connected?).to be_falsey
|
115
144
|
end
|
116
145
|
|
@@ -119,7 +148,7 @@ describe ::ActiveRecord::Base do
|
|
119
148
|
context 'current tenant not established' do
|
120
149
|
|
121
150
|
it 'rises an error' do
|
122
|
-
Motel::Manager.
|
151
|
+
Motel::Manager.switch_tenant(nil)
|
123
152
|
expect{::ActiveRecord::Base.connected?}.to raise_error Motel::NoCurrentTenantError
|
124
153
|
end
|
125
154
|
|
@@ -133,7 +162,7 @@ describe ::ActiveRecord::Base do
|
|
133
162
|
|
134
163
|
it 'removes connection' do
|
135
164
|
::ActiveRecord::Base.connection_handler.establish_connection('foo')
|
136
|
-
Motel::Manager.
|
165
|
+
Motel::Manager.switch_tenant('foo')
|
137
166
|
::ActiveRecord::Base.remove_connection
|
138
167
|
expect(::ActiveRecord::Base.connection_handler.active_tenants).not_to include('foo')
|
139
168
|
end
|
@@ -143,7 +172,7 @@ describe ::ActiveRecord::Base do
|
|
143
172
|
context 'current tenant not established' do
|
144
173
|
|
145
174
|
it 'rises an error' do
|
146
|
-
Motel::Manager.
|
175
|
+
Motel::Manager.switch_tenant(nil)
|
147
176
|
expect{::ActiveRecord::Base.remove_connection}.to raise_error Motel::NoCurrentTenantError
|
148
177
|
end
|
149
178
|
|
@@ -164,7 +193,7 @@ describe ::ActiveRecord::Base do
|
|
164
193
|
context 'tenant enviroment variable or current tenant or default tenant are set' do
|
165
194
|
|
166
195
|
it 'returns the current tenant' do
|
167
|
-
Motel::Manager.
|
196
|
+
Motel::Manager.switch_tenant('foo')
|
168
197
|
|
169
198
|
expect(::ActiveRecord::Base.current_tenant).to eq 'foo'
|
170
199
|
end
|
@@ -174,7 +203,7 @@ describe ::ActiveRecord::Base do
|
|
174
203
|
context 'no tenant has been established' do
|
175
204
|
|
176
205
|
it 'rises an error' do
|
177
|
-
Motel::Manager.
|
206
|
+
Motel::Manager.switch_tenant(nil)
|
178
207
|
|
179
208
|
expect{::ActiveRecord::Base.current_tenant}.to raise_error Motel::NoCurrentTenantError
|
180
209
|
end
|
@@ -20,7 +20,7 @@ describe Motel::Manager do
|
|
20
20
|
|
21
21
|
after(:each) do
|
22
22
|
ENV['TENANT'] = nil
|
23
|
-
@manager.
|
23
|
+
@manager.switch_tenant(nil)
|
24
24
|
@manager.default_tenant = nil
|
25
25
|
|
26
26
|
# Remove all connections tenant
|
@@ -120,14 +120,6 @@ describe Motel::Manager do
|
|
120
120
|
expect(@manager.tenant?('foo')).to be_truthy
|
121
121
|
end
|
122
122
|
|
123
|
-
it 'returns true if tenant baz does exist' do
|
124
|
-
resolver = Motel::ConnectionAdapters::ConnectionSpecification::Resolver.new
|
125
|
-
spec = resolver.spec(BAZ_SPEC)
|
126
|
-
handler = ::ActiveRecord::Base.connection_handler
|
127
|
-
handler.establish_connection('baz', spec)
|
128
|
-
expect(@manager.tenant?('baz')).to be_truthy
|
129
|
-
end
|
130
|
-
|
131
123
|
it 'returns false if tenant does not exist' do
|
132
124
|
expect(@manager.tenant?('foobar')).to be_falsey
|
133
125
|
end
|
@@ -193,16 +185,17 @@ describe Motel::Manager do
|
|
193
185
|
|
194
186
|
end
|
195
187
|
|
196
|
-
describe '#
|
188
|
+
describe '#current_tenant' do
|
197
189
|
|
198
190
|
context 'tenant environment variable, current tenant and default tenant are set' do
|
199
191
|
|
200
192
|
it 'returns tenant enviroment variable' do
|
201
193
|
ENV['TENANT'] = 'foo'
|
202
|
-
@manager.current_tenant = 'bar'
|
203
194
|
@manager.default_tenant = 'baz'
|
204
195
|
|
205
|
-
|
196
|
+
@manager.switch_tenant('bar')
|
197
|
+
|
198
|
+
expect(@manager.current_tenant).to eq ENV['TENANT']
|
206
199
|
end
|
207
200
|
|
208
201
|
end
|
@@ -211,10 +204,11 @@ describe Motel::Manager do
|
|
211
204
|
|
212
205
|
it 'returns tenant enviroment variable' do
|
213
206
|
ENV['TENANT'] = nil
|
214
|
-
@manager.current_tenant = 'bar'
|
215
207
|
@manager.default_tenant = 'baz'
|
216
208
|
|
217
|
-
|
209
|
+
@manager.switch_tenant('bar')
|
210
|
+
|
211
|
+
expect(@manager.current_tenant).to eq 'bar'
|
218
212
|
end
|
219
213
|
|
220
214
|
end
|
@@ -223,10 +217,11 @@ describe Motel::Manager do
|
|
223
217
|
|
224
218
|
it 'returns tenant enviroment variable' do
|
225
219
|
ENV['TENANT'] = nil
|
226
|
-
@manager.current_tenant = nil
|
227
220
|
@manager.default_tenant = 'baz'
|
228
221
|
|
229
|
-
|
222
|
+
@manager.switch_tenant(nil)
|
223
|
+
|
224
|
+
expect(@manager.current_tenant).to eq 'baz'
|
230
225
|
end
|
231
226
|
|
232
227
|
end
|
data/spec/tmp/tenants.sqlite3
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motel-activerecord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Diego Martínez Valdelamar
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -128,10 +128,8 @@ files:
|
|
128
128
|
- lib/motel/connection_adapters/connection_specification/resolver.rb
|
129
129
|
- lib/motel/connection_adapters/connection_specification.rb
|
130
130
|
- lib/motel/connection_adapters/connection_handler.rb
|
131
|
-
- lib/motel/lobby.rb
|
132
|
-
- lib/motel/active_record/query_cache.rb
|
133
|
-
- lib/motel/active_record/migration.rb
|
134
131
|
- lib/motel/active_record/connection_handler.rb
|
132
|
+
- lib/motel/active_record/railties/databases.rake
|
135
133
|
- VERSION
|
136
134
|
- README.md
|
137
135
|
- spec/tmp/foo.sqlite3
|
@@ -142,7 +140,6 @@ files:
|
|
142
140
|
- spec/lib/motel/sources/redis_spec.rb
|
143
141
|
- spec/lib/motel/connection_adapters/connection_specification/resolver_spec.rb
|
144
142
|
- spec/lib/motel/connection_adapters/connection_handler_spec.rb
|
145
|
-
- spec/lib/motel/lobby_spec.rb
|
146
143
|
- spec/lib/motel/manager_spec.rb
|
147
144
|
- spec/lib/motel/active_record/connection_handler.rb
|
148
145
|
homepage: https://github.com/dimarval/motel-activerecord
|
@@ -178,7 +175,6 @@ test_files:
|
|
178
175
|
- spec/lib/motel/sources/redis_spec.rb
|
179
176
|
- spec/lib/motel/connection_adapters/connection_specification/resolver_spec.rb
|
180
177
|
- spec/lib/motel/connection_adapters/connection_handler_spec.rb
|
181
|
-
- spec/lib/motel/lobby_spec.rb
|
182
178
|
- spec/lib/motel/manager_spec.rb
|
183
179
|
- spec/lib/motel/active_record/connection_handler.rb
|
184
180
|
has_rdoc:
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
|
3
|
-
module Motel
|
4
|
-
module ActiveRecord
|
5
|
-
module Migration
|
6
|
-
module CheckPending
|
7
|
-
|
8
|
-
def call(env)
|
9
|
-
return @app.call(env) unless Motel::Manager.determines_tenant
|
10
|
-
|
11
|
-
if connection.supports_migrations?
|
12
|
-
mtime = ::ActiveRecord::Migrator.last_migration.mtime.to_i
|
13
|
-
if @last_check < mtime
|
14
|
-
::ActiveRecord::Migration.check_pending!(connection)
|
15
|
-
@last_check = mtime
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
@app.call(env)
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def connection
|
25
|
-
::ActiveRecord::Base.connection
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class ActiveRecord::Migration::CheckPending
|
34
|
-
prepend Motel::ActiveRecord::Migration::CheckPending
|
35
|
-
end
|
36
|
-
|
@@ -1,73 +0,0 @@
|
|
1
|
-
require 'active_record'
|
2
|
-
|
3
|
-
module Motel
|
4
|
-
module ActiveRecord
|
5
|
-
module QueryCache
|
6
|
-
|
7
|
-
module ClassMethods
|
8
|
-
|
9
|
-
# Enable the query cache within the block if Active Record is configured.
|
10
|
-
# If it's not, it will execute the given block.
|
11
|
-
def cache(&block)
|
12
|
-
if Motel::Manager.determines_tenant &&
|
13
|
-
::ActiveRecord::Base.connected?
|
14
|
-
connection.cache(&block)
|
15
|
-
else
|
16
|
-
yield
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
# Disable the query cache within the block if Active Record is configured.
|
21
|
-
# If it's not, it will execute the given block.
|
22
|
-
def uncached(&block)
|
23
|
-
if Motel::Manager.determines_tenant &&
|
24
|
-
::ActiveRecord::Base.connected?
|
25
|
-
connection.uncached(&block)
|
26
|
-
else
|
27
|
-
yield
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
def call(env)
|
34
|
-
if Motel::Manager.determines_tenant
|
35
|
-
connection = ::ActiveRecord::Base.connection
|
36
|
-
enabled = connection.query_cache_enabled
|
37
|
-
connection_id = ::ActiveRecord::Base.connection_id
|
38
|
-
connection.enable_query_cache!
|
39
|
-
|
40
|
-
response = @app.call(env)
|
41
|
-
response[2] = Rack::BodyProxy.new(response[2]) do
|
42
|
-
restore_query_cache_settings(connection_id, enabled)
|
43
|
-
end
|
44
|
-
|
45
|
-
response
|
46
|
-
else
|
47
|
-
@app.call(env)
|
48
|
-
end
|
49
|
-
rescue Exception => e
|
50
|
-
if Motel::Manager.determines_tenant
|
51
|
-
restore_query_cache_settings(connection_id, enabled)
|
52
|
-
end
|
53
|
-
|
54
|
-
raise e
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
class ::ActiveRecord::Base
|
63
|
-
extend Motel::ActiveRecord::QueryCache::ClassMethods
|
64
|
-
end
|
65
|
-
|
66
|
-
class ::ActiveRecord::QueryCache
|
67
|
-
prepend Motel::ActiveRecord::QueryCache
|
68
|
-
end
|
69
|
-
|
70
|
-
class ::ActiveRecord::ConnectionAdapters::AbstractAdapter
|
71
|
-
prepend Motel::ActiveRecord::QueryCache::ClassMethods
|
72
|
-
end
|
73
|
-
|
data/lib/motel/lobby.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'rack'
|
2
|
-
|
3
|
-
module Motel
|
4
|
-
|
5
|
-
class Lobby
|
6
|
-
|
7
|
-
def initialize(app)
|
8
|
-
@app = app
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(env)
|
12
|
-
request = Rack::Request.new(env)
|
13
|
-
name = tenant_name(request)
|
14
|
-
|
15
|
-
if name && Motel::Manager.tenant?(name)
|
16
|
-
Motel::Manager.current_tenant = name
|
17
|
-
else
|
18
|
-
Motel::Manager.current_tenant = nil
|
19
|
-
end
|
20
|
-
|
21
|
-
@app.call(env)
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def tenant_name(request)
|
27
|
-
if Motel::Manager.admission_criteria
|
28
|
-
regex = Regexp.new(Motel::Manager.admission_criteria)
|
29
|
-
name = request.path.match(regex)
|
30
|
-
name[1] if name
|
31
|
-
else
|
32
|
-
request.host.split('.').first
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
@@ -1,133 +0,0 @@
|
|
1
|
-
ENV['RACK_ENV'] = 'test'
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
require 'rack/test'
|
5
|
-
require 'tempfile'
|
6
|
-
|
7
|
-
describe Motel::Lobby do
|
8
|
-
include Rack::Test::Methods
|
9
|
-
|
10
|
-
def app
|
11
|
-
app = lambda{ |env| [200, {"Content-Type" => "text/html"}, "Test"] }
|
12
|
-
Motel::Lobby.new(app)
|
13
|
-
end
|
14
|
-
|
15
|
-
before(:all) do
|
16
|
-
Motel::Manager.add_tenant('foo', FOO_SPEC)
|
17
|
-
end
|
18
|
-
|
19
|
-
after(:all) do
|
20
|
-
Motel::Manager.delete_tenant('foo')
|
21
|
-
Motel::Manager.admission_criteria = nil #sets default
|
22
|
-
end
|
23
|
-
|
24
|
-
describe '#call' do
|
25
|
-
|
26
|
-
context 'default admission criteria' do
|
27
|
-
|
28
|
-
before(:all) do
|
29
|
-
Motel::Manager.admission_criteria = nil
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'url match' do
|
33
|
-
|
34
|
-
context 'existing tenant' do
|
35
|
-
|
36
|
-
before(:each) do
|
37
|
-
@url = 'http://foo.test.com'
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'sets the current tenant' do
|
41
|
-
request @url
|
42
|
-
|
43
|
-
expect(Motel::Manager.current_tenant).to eq 'foo'
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'response is ok' do
|
47
|
-
request @url
|
48
|
-
|
49
|
-
expect(last_response).to be_ok
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
context 'nonexistent tenant' do
|
55
|
-
|
56
|
-
before(:each) do
|
57
|
-
@url = 'http://bar.test.com'
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'sets the current tenant on nil' do
|
61
|
-
request @url
|
62
|
-
|
63
|
-
expect(Motel::Manager.current_tenant).to be_nil
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'response is ok' do
|
67
|
-
request @url
|
68
|
-
|
69
|
-
expect(last_response).to be_ok
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
context 'specifying admission criteria' do
|
81
|
-
|
82
|
-
before(:all) do
|
83
|
-
Motel::Manager.admission_criteria = 'tenants\/(\w*)'
|
84
|
-
end
|
85
|
-
|
86
|
-
context 'url match' do
|
87
|
-
|
88
|
-
context 'existing tenant' do
|
89
|
-
|
90
|
-
before(:each) do
|
91
|
-
@url = 'http://www.example.com/tenants/foo'
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'sets the current tenant' do
|
95
|
-
request @url
|
96
|
-
|
97
|
-
expect(Motel::Manager.current_tenant).to eq 'foo'
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'response is ok' do
|
101
|
-
request @url
|
102
|
-
|
103
|
-
expect(last_response).to be_ok
|
104
|
-
end
|
105
|
-
|
106
|
-
end
|
107
|
-
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'url does not match' do
|
111
|
-
|
112
|
-
before(:each) do
|
113
|
-
@url = 'http://example.com'
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'sets null the current tenant' do
|
117
|
-
request @url
|
118
|
-
|
119
|
-
expect(Motel::Manager.current_tenant).to be_nil
|
120
|
-
end
|
121
|
-
|
122
|
-
it 'response is ok' do
|
123
|
-
request @url
|
124
|
-
|
125
|
-
expect(last_response).to be_ok
|
126
|
-
end
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
|
-
end
|
131
|
-
|
132
|
-
end
|
133
|
-
|