ros-apartment 2.3.0.alpha2 → 2.6.1
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/.github/workflows/.rubocop-linter.yml +22 -0
- data/.pryrc +5 -3
- data/.rubocop.yml +21 -0
- data/.rubocop_todo.yml +29 -0
- data/.story_branch.yml +4 -0
- data/.travis.yml +15 -36
- data/Appraisals +16 -29
- data/Gemfile +4 -1
- data/Guardfile +3 -1
- data/HISTORY.md +7 -0
- data/README.md +80 -39
- data/Rakefile +45 -23
- data/apartment.gemspec +33 -25
- data/gemfiles/rails_4_2.gemfile +12 -10
- data/gemfiles/rails_5_0.gemfile +2 -1
- data/gemfiles/rails_5_1.gemfile +2 -1
- data/gemfiles/rails_5_2.gemfile +2 -1
- data/gemfiles/rails_6_0.gemfile +6 -5
- data/gemfiles/rails_master.gemfile +2 -1
- data/lib/apartment.rb +36 -11
- data/lib/apartment/active_record/connection_handling.rb +17 -0
- data/lib/apartment/active_record/internal_metadata.rb +11 -0
- data/lib/apartment/active_record/schema_migration.rb +13 -0
- data/lib/apartment/adapters/abstract_adapter.rb +50 -45
- data/lib/apartment/adapters/abstract_jdbc_adapter.rb +4 -3
- data/lib/apartment/adapters/jdbc_mysql_adapter.rb +3 -3
- data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +20 -13
- data/lib/apartment/adapters/mysql2_adapter.rb +10 -9
- data/lib/apartment/adapters/postgis_adapter.rb +3 -2
- data/lib/apartment/adapters/postgresql_adapter.rb +55 -27
- data/lib/apartment/adapters/sqlite3_adapter.rb +18 -8
- data/lib/apartment/console.rb +35 -3
- data/lib/apartment/custom_console.rb +42 -0
- data/lib/apartment/deprecation.rb +2 -1
- data/lib/apartment/elevators/domain.rb +4 -3
- data/lib/apartment/elevators/first_subdomain.rb +3 -2
- data/lib/apartment/elevators/generic.rb +4 -3
- data/lib/apartment/elevators/host.rb +6 -1
- data/lib/apartment/elevators/host_hash.rb +6 -2
- data/lib/apartment/elevators/subdomain.rb +9 -5
- data/lib/apartment/migrator.rb +4 -3
- data/lib/apartment/model.rb +27 -0
- data/lib/apartment/railtie.rb +26 -15
- data/lib/apartment/reloader.rb +2 -1
- data/lib/apartment/tasks/enhancements.rb +4 -6
- data/lib/apartment/tenant.rb +19 -9
- data/lib/apartment/version.rb +3 -1
- data/lib/generators/apartment/install/install_generator.rb +4 -3
- data/lib/generators/apartment/install/templates/apartment.rb +3 -2
- data/lib/tasks/apartment.rake +24 -19
- metadata +79 -256
- data/spec/adapters/jdbc_mysql_adapter_spec.rb +0 -19
- data/spec/adapters/jdbc_postgresql_adapter_spec.rb +0 -41
- data/spec/adapters/mysql2_adapter_spec.rb +0 -59
- data/spec/adapters/postgresql_adapter_spec.rb +0 -61
- data/spec/adapters/sqlite3_adapter_spec.rb +0 -83
- data/spec/apartment_spec.rb +0 -11
- data/spec/config/database.yml.sample +0 -49
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/controllers/application_controller.rb +0 -6
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/app/models/company.rb +0 -3
- data/spec/dummy/app/models/user.rb +0 -3
- data/spec/dummy/app/views/application/index.html.erb +0 -1
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/config/application.rb +0 -49
- data/spec/dummy/config/boot.rb +0 -11
- data/spec/dummy/config/database.yml.sample +0 -44
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -28
- data/spec/dummy/config/environments/production.rb +0 -51
- data/spec/dummy/config/environments/test.rb +0 -34
- data/spec/dummy/config/initializers/apartment.rb +0 -4
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/inflections.rb +0 -10
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -7
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -3
- data/spec/dummy/db/migrate/20110613152810_create_dummy_models.rb +0 -39
- data/spec/dummy/db/migrate/20111202022214_create_table_books.rb +0 -14
- data/spec/dummy/db/migrate/20180415260934_create_public_tokens.rb +0 -13
- data/spec/dummy/db/schema.rb +0 -55
- data/spec/dummy/db/seeds.rb +0 -5
- data/spec/dummy/db/seeds/import.rb +0 -5
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -26
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +0 -6
- data/spec/dummy_engine/.gitignore +0 -8
- data/spec/dummy_engine/Gemfile +0 -15
- data/spec/dummy_engine/Rakefile +0 -34
- data/spec/dummy_engine/bin/rails +0 -12
- data/spec/dummy_engine/config/initializers/apartment.rb +0 -51
- data/spec/dummy_engine/dummy_engine.gemspec +0 -24
- data/spec/dummy_engine/lib/dummy_engine.rb +0 -4
- data/spec/dummy_engine/lib/dummy_engine/engine.rb +0 -4
- data/spec/dummy_engine/lib/dummy_engine/version.rb +0 -3
- data/spec/dummy_engine/test/dummy/Rakefile +0 -6
- data/spec/dummy_engine/test/dummy/config.ru +0 -4
- data/spec/dummy_engine/test/dummy/config/application.rb +0 -22
- data/spec/dummy_engine/test/dummy/config/boot.rb +0 -5
- data/spec/dummy_engine/test/dummy/config/database.yml +0 -25
- data/spec/dummy_engine/test/dummy/config/environment.rb +0 -5
- data/spec/dummy_engine/test/dummy/config/environments/development.rb +0 -37
- data/spec/dummy_engine/test/dummy/config/environments/production.rb +0 -78
- data/spec/dummy_engine/test/dummy/config/environments/test.rb +0 -39
- data/spec/dummy_engine/test/dummy/config/initializers/assets.rb +0 -8
- data/spec/dummy_engine/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy_engine/test/dummy/config/initializers/cookies_serializer.rb +0 -3
- data/spec/dummy_engine/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
- data/spec/dummy_engine/test/dummy/config/initializers/inflections.rb +0 -16
- data/spec/dummy_engine/test/dummy/config/initializers/mime_types.rb +0 -4
- data/spec/dummy_engine/test/dummy/config/initializers/session_store.rb +0 -3
- data/spec/dummy_engine/test/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy_engine/test/dummy/config/locales/en.yml +0 -23
- data/spec/dummy_engine/test/dummy/config/routes.rb +0 -56
- data/spec/dummy_engine/test/dummy/config/secrets.yml +0 -22
- data/spec/examples/connection_adapter_examples.rb +0 -42
- data/spec/examples/generic_adapter_custom_configuration_example.rb +0 -95
- data/spec/examples/generic_adapter_examples.rb +0 -163
- data/spec/examples/schema_adapter_examples.rb +0 -234
- data/spec/integration/apartment_rake_integration_spec.rb +0 -107
- data/spec/integration/query_caching_spec.rb +0 -81
- data/spec/integration/use_within_an_engine_spec.rb +0 -28
- data/spec/schemas/v1.rb +0 -16
- data/spec/schemas/v2.rb +0 -43
- data/spec/schemas/v3.rb +0 -49
- data/spec/spec_helper.rb +0 -61
- data/spec/support/apartment_helpers.rb +0 -43
- data/spec/support/capybara_sessions.rb +0 -15
- data/spec/support/config.rb +0 -10
- data/spec/support/contexts.rb +0 -52
- data/spec/support/requirements.rb +0 -35
- data/spec/support/setup.rb +0 -46
- data/spec/tasks/apartment_rake_spec.rb +0 -129
- data/spec/tenant_spec.rb +0 -190
- data/spec/unit/config_spec.rb +0 -112
- data/spec/unit/elevators/domain_spec.rb +0 -32
- data/spec/unit/elevators/first_subdomain_spec.rb +0 -24
- data/spec/unit/elevators/generic_spec.rb +0 -54
- data/spec/unit/elevators/host_hash_spec.rb +0 -32
- data/spec/unit/elevators/host_spec.rb +0 -89
- data/spec/unit/elevators/subdomain_spec.rb +0 -76
- data/spec/unit/migrator_spec.rb +0 -77
- data/spec/unit/reloader_spec.rb +0 -24
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module ConnectionHandling
|
|
5
|
+
def connected_to_with_tenant(database: nil, role: nil, prevent_writes: false, &blk)
|
|
6
|
+
current_tenant = Apartment::Tenant.current
|
|
7
|
+
|
|
8
|
+
connected_to_without_tenant(database: database, role: role, prevent_writes: prevent_writes) do
|
|
9
|
+
Apartment::Tenant.switch!(current_tenant)
|
|
10
|
+
yield(blk)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
alias connected_to_without_tenant connected_to
|
|
15
|
+
alias connected_to connected_to_with_tenant
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# rubocop:disable Rails/ApplicationRecord
|
|
4
|
+
class InternalMetadata < ActiveRecord::Base # :nodoc:
|
|
5
|
+
class << self
|
|
6
|
+
def table_exists?
|
|
7
|
+
connection.table_exists?(table_name)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
# rubocop:enable Rails/ApplicationRecord
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
# rubocop:disable Rails/ApplicationRecord
|
|
5
|
+
class SchemaMigration < ActiveRecord::Base # :nodoc:
|
|
6
|
+
class << self
|
|
7
|
+
def table_exists?
|
|
8
|
+
connection.table_exists?(table_name)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
# rubocop:enable Rails/ApplicationRecord
|
|
13
|
+
end
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Apartment
|
|
2
4
|
module Adapters
|
|
5
|
+
# rubocop:disable Metrics/ClassLength
|
|
3
6
|
class AbstractAdapter
|
|
4
7
|
include ActiveSupport::Callbacks
|
|
5
8
|
define_callbacks :create, :switch
|
|
@@ -32,6 +35,12 @@ module Apartment
|
|
|
32
35
|
end
|
|
33
36
|
end
|
|
34
37
|
|
|
38
|
+
# Initialize Apartment config options such as excluded_models
|
|
39
|
+
#
|
|
40
|
+
def init
|
|
41
|
+
process_excluded_models
|
|
42
|
+
end
|
|
43
|
+
|
|
35
44
|
# Note alias_method here doesn't work with inheritence apparently ??
|
|
36
45
|
#
|
|
37
46
|
def current
|
|
@@ -45,7 +54,7 @@ module Apartment
|
|
|
45
54
|
def default_tenant
|
|
46
55
|
@default_tenant || Apartment.default_tenant
|
|
47
56
|
end
|
|
48
|
-
alias
|
|
57
|
+
alias default_schema default_tenant # TODO: deprecate default_schema
|
|
49
58
|
|
|
50
59
|
# Drop the tenant
|
|
51
60
|
#
|
|
@@ -55,9 +64,8 @@ module Apartment
|
|
|
55
64
|
with_neutral_connection(tenant) do |conn|
|
|
56
65
|
drop_command(conn, tenant)
|
|
57
66
|
end
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
raise_drop_tenant_error!(tenant, exception)
|
|
67
|
+
rescue *rescuable_exceptions => e
|
|
68
|
+
raise_drop_tenant_error!(tenant, e)
|
|
61
69
|
end
|
|
62
70
|
|
|
63
71
|
# Switch to a new tenant
|
|
@@ -66,8 +74,6 @@ module Apartment
|
|
|
66
74
|
#
|
|
67
75
|
def switch!(tenant = nil)
|
|
68
76
|
run_callbacks :switch do
|
|
69
|
-
return reset if tenant.nil?
|
|
70
|
-
|
|
71
77
|
connect_to_new(tenant).tap do
|
|
72
78
|
Apartment.connection.clear_query_cache
|
|
73
79
|
end
|
|
@@ -79,13 +85,14 @@ module Apartment
|
|
|
79
85
|
# @param {String?} tenant to connect to
|
|
80
86
|
#
|
|
81
87
|
def switch(tenant = nil)
|
|
88
|
+
previous_tenant = current
|
|
89
|
+
switch!(tenant)
|
|
90
|
+
yield
|
|
91
|
+
ensure
|
|
82
92
|
begin
|
|
83
|
-
previous_tenant
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
ensure
|
|
88
|
-
switch!(previous_tenant) rescue reset
|
|
93
|
+
switch!(previous_tenant)
|
|
94
|
+
rescue StandardError => _e
|
|
95
|
+
reset
|
|
89
96
|
end
|
|
90
97
|
end
|
|
91
98
|
|
|
@@ -93,14 +100,15 @@ module Apartment
|
|
|
93
100
|
#
|
|
94
101
|
def each(tenants = Apartment.tenant_names)
|
|
95
102
|
tenants.each do |tenant|
|
|
96
|
-
switch(tenant){ yield tenant }
|
|
103
|
+
switch(tenant) { yield tenant }
|
|
97
104
|
end
|
|
98
105
|
end
|
|
99
106
|
|
|
100
107
|
# Establish a new connection for each specific excluded model
|
|
101
108
|
#
|
|
102
109
|
def process_excluded_models
|
|
103
|
-
# All other models will shared a connection (at Apartment.connection_class)
|
|
110
|
+
# All other models will shared a connection (at Apartment.connection_class)
|
|
111
|
+
# and we can modify at will
|
|
104
112
|
Apartment.excluded_models.each do |excluded_model|
|
|
105
113
|
process_excluded_model(excluded_model)
|
|
106
114
|
end
|
|
@@ -116,9 +124,9 @@ module Apartment
|
|
|
116
124
|
#
|
|
117
125
|
def seed_data
|
|
118
126
|
# Don't log the output of seeding the db
|
|
119
|
-
silence_warnings{ load_or_raise(Apartment.seed_data_file) } if Apartment.seed_data_file
|
|
127
|
+
silence_warnings { load_or_raise(Apartment.seed_data_file) } if Apartment.seed_data_file
|
|
120
128
|
end
|
|
121
|
-
|
|
129
|
+
alias seed seed_data
|
|
122
130
|
|
|
123
131
|
# Prepend the environment if configured and the environment isn't already there
|
|
124
132
|
#
|
|
@@ -126,20 +134,18 @@ module Apartment
|
|
|
126
134
|
# @return {String} tenant name with Rails environment *optionally* prepended
|
|
127
135
|
#
|
|
128
136
|
def environmentify(tenant)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
tenant
|
|
136
|
-
end
|
|
137
|
+
return tenant if tenant.nil? || tenant.include?(Rails.env)
|
|
138
|
+
|
|
139
|
+
if Apartment.prepend_environment
|
|
140
|
+
"#{Rails.env}_#{tenant}"
|
|
141
|
+
elsif Apartment.append_environment
|
|
142
|
+
"#{tenant}_#{Rails.env}"
|
|
137
143
|
else
|
|
138
144
|
tenant
|
|
139
145
|
end
|
|
140
146
|
end
|
|
141
147
|
|
|
142
|
-
|
|
148
|
+
protected
|
|
143
149
|
|
|
144
150
|
def process_excluded_model(excluded_model)
|
|
145
151
|
excluded_model.constantize.establish_connection @config
|
|
@@ -158,8 +164,8 @@ module Apartment
|
|
|
158
164
|
with_neutral_connection(tenant) do |conn|
|
|
159
165
|
create_tenant_command(conn, tenant)
|
|
160
166
|
end
|
|
161
|
-
rescue *rescuable_exceptions =>
|
|
162
|
-
raise_create_tenant_error!(tenant,
|
|
167
|
+
rescue *rescuable_exceptions => e
|
|
168
|
+
raise_create_tenant_error!(tenant, e)
|
|
163
169
|
end
|
|
164
170
|
|
|
165
171
|
def create_tenant_command(conn, tenant)
|
|
@@ -171,21 +177,23 @@ module Apartment
|
|
|
171
177
|
# @param {String} tenant Database name
|
|
172
178
|
#
|
|
173
179
|
def connect_to_new(tenant)
|
|
180
|
+
return reset if tenant.nil?
|
|
181
|
+
|
|
174
182
|
query_cache_enabled = ActiveRecord::Base.connection.query_cache_enabled
|
|
175
183
|
|
|
176
184
|
Apartment.establish_connection multi_tenantify(tenant)
|
|
177
|
-
Apartment.connection.active?
|
|
185
|
+
Apartment.connection.active? # call active? to manually check if this connection is valid
|
|
178
186
|
|
|
179
187
|
Apartment.connection.enable_query_cache! if query_cache_enabled
|
|
180
|
-
rescue *rescuable_exceptions =>
|
|
188
|
+
rescue *rescuable_exceptions => e
|
|
181
189
|
Apartment::Tenant.reset if reset_on_connection_exception?
|
|
182
|
-
raise_connect_error!(tenant,
|
|
190
|
+
raise_connect_error!(tenant, e)
|
|
183
191
|
end
|
|
184
192
|
|
|
185
193
|
# Import the database schema
|
|
186
194
|
#
|
|
187
195
|
def import_database_schema
|
|
188
|
-
ActiveRecord::Schema.verbose = false
|
|
196
|
+
ActiveRecord::Schema.verbose = false # do not log schema load output.
|
|
189
197
|
|
|
190
198
|
load_or_raise(Apartment.database_schema_file) if Apartment.database_schema_file
|
|
191
199
|
end
|
|
@@ -196,9 +204,7 @@ module Apartment
|
|
|
196
204
|
# if false, use the default db name from the db
|
|
197
205
|
def multi_tenantify(tenant, with_database = true)
|
|
198
206
|
db_connection_config(tenant).tap do |config|
|
|
199
|
-
if with_database
|
|
200
|
-
multi_tenantify_with_tenant_db_name(config, tenant)
|
|
201
|
-
end
|
|
207
|
+
multi_tenantify_with_tenant_db_name(config, tenant) if with_database
|
|
202
208
|
end
|
|
203
209
|
end
|
|
204
210
|
|
|
@@ -209,14 +215,12 @@ module Apartment
|
|
|
209
215
|
# Load a file or raise error if it doesn't exists
|
|
210
216
|
#
|
|
211
217
|
def load_or_raise(file)
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
raise FileNotFound, "#{file} doesn't exist yet"
|
|
216
|
-
end
|
|
218
|
+
raise FileNotFound, "#{file} doesn't exist yet" unless File.exist?(file)
|
|
219
|
+
|
|
220
|
+
load(file)
|
|
217
221
|
end
|
|
218
222
|
# Backward compatibility
|
|
219
|
-
|
|
223
|
+
alias load_or_abort load_or_raise
|
|
220
224
|
|
|
221
225
|
# Exceptions to rescue from on db operations
|
|
222
226
|
#
|
|
@@ -231,10 +235,10 @@ module Apartment
|
|
|
231
235
|
end
|
|
232
236
|
|
|
233
237
|
def db_connection_config(tenant)
|
|
234
|
-
Apartment.db_config_for(tenant).
|
|
238
|
+
Apartment.db_config_for(tenant).dup
|
|
235
239
|
end
|
|
236
240
|
|
|
237
|
-
|
|
241
|
+
def with_neutral_connection(tenant, &_block)
|
|
238
242
|
if Apartment.with_multi_server_setup
|
|
239
243
|
# neutral connection is necessary whenever you need to create/remove a database from a server.
|
|
240
244
|
# example: when you use postgresql, you need to connect to the default postgresql database before you create your own.
|
|
@@ -251,19 +255,20 @@ module Apartment
|
|
|
251
255
|
end
|
|
252
256
|
|
|
253
257
|
def raise_drop_tenant_error!(tenant, exception)
|
|
254
|
-
raise TenantNotFound, "Error while dropping tenant #{environmentify(tenant)}: #{
|
|
258
|
+
raise TenantNotFound, "Error while dropping tenant #{environmentify(tenant)}: #{exception.message}"
|
|
255
259
|
end
|
|
256
260
|
|
|
257
261
|
def raise_create_tenant_error!(tenant, exception)
|
|
258
|
-
raise TenantExists, "Error while creating tenant #{environmentify(tenant)}: #{
|
|
262
|
+
raise TenantExists, "Error while creating tenant #{environmentify(tenant)}: #{exception.message}"
|
|
259
263
|
end
|
|
260
264
|
|
|
261
265
|
def raise_connect_error!(tenant, exception)
|
|
262
|
-
raise TenantNotFound, "Error while connecting to tenant #{environmentify(tenant)}: #{
|
|
266
|
+
raise TenantNotFound, "Error while connecting to tenant #{environmentify(tenant)}: #{exception.message}"
|
|
263
267
|
end
|
|
264
268
|
|
|
265
269
|
class SeparateDbConnectionHandler < ::ActiveRecord::Base
|
|
266
270
|
end
|
|
267
271
|
end
|
|
268
272
|
end
|
|
273
|
+
# rubocop:enable Metrics/ClassLength
|
|
269
274
|
end
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'apartment/adapters/abstract_adapter'
|
|
2
4
|
|
|
3
5
|
module Apartment
|
|
4
6
|
module Adapters
|
|
5
7
|
class AbstractJDBCAdapter < AbstractAdapter
|
|
6
|
-
|
|
7
|
-
private
|
|
8
|
+
private
|
|
8
9
|
|
|
9
10
|
def multi_tenantify_with_tenant_db_name(config, tenant)
|
|
10
|
-
config[:url] = "#{config[:url].gsub(
|
|
11
|
+
config[:url] = "#{config[:url].gsub(%r{(\S+)\/.+$}, '\1')}/#{environmentify(tenant)}"
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
def rescue_from
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require 'apartment/adapters/abstract_jdbc_adapter'
|
|
4
4
|
|
|
5
|
+
module Apartment
|
|
5
6
|
module Tenant
|
|
6
7
|
def self.jdbc_mysql_adapter(config)
|
|
7
8
|
Adapters::JDBCMysqlAdapter.new config
|
|
@@ -10,7 +11,6 @@ module Apartment
|
|
|
10
11
|
|
|
11
12
|
module Adapters
|
|
12
13
|
class JDBCMysqlAdapter < AbstractJDBCAdapter
|
|
13
|
-
|
|
14
14
|
def reset_on_connection_exception?
|
|
15
15
|
true
|
|
16
16
|
end
|
|
@@ -1,28 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'apartment/adapters/postgresql_adapter'
|
|
2
4
|
|
|
3
5
|
module Apartment
|
|
4
6
|
module Tenant
|
|
5
|
-
|
|
6
7
|
def self.jdbc_postgresql_adapter(config)
|
|
7
|
-
Apartment.use_schemas
|
|
8
|
-
Adapters::JDBCPostgresqlSchemaAdapter.new(config)
|
|
8
|
+
if Apartment.use_schemas
|
|
9
|
+
Adapters::JDBCPostgresqlSchemaAdapter.new(config)
|
|
10
|
+
else
|
|
9
11
|
Adapters::JDBCPostgresqlAdapter.new(config)
|
|
12
|
+
end
|
|
10
13
|
end
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
module Adapters
|
|
14
|
-
|
|
15
17
|
# Default adapter when not using Postgresql Schemas
|
|
16
18
|
class JDBCPostgresqlAdapter < PostgresqlAdapter
|
|
17
|
-
|
|
18
|
-
private
|
|
19
|
+
private
|
|
19
20
|
|
|
20
21
|
def multi_tenantify_with_tenant_db_name(config, tenant)
|
|
21
|
-
config[:url] = "#{config[:url].gsub(
|
|
22
|
+
config[:url] = "#{config[:url].gsub(%r{(\S+)\/.+$}, '\1')}/#{environmentify(tenant)}"
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def create_tenant_command(conn, tenant)
|
|
25
|
-
conn.create_database(environmentify(tenant),
|
|
26
|
+
conn.create_database(environmentify(tenant), thisisahack: '')
|
|
26
27
|
end
|
|
27
28
|
|
|
28
29
|
def rescue_from
|
|
@@ -32,21 +33,27 @@ module Apartment
|
|
|
32
33
|
|
|
33
34
|
# Separate Adapter for Postgresql when using schemas
|
|
34
35
|
class JDBCPostgresqlSchemaAdapter < PostgresqlSchemaAdapter
|
|
35
|
-
|
|
36
36
|
# Set schema search path to new schema
|
|
37
37
|
#
|
|
38
38
|
def connect_to_new(tenant = nil)
|
|
39
39
|
return reset if tenant.nil?
|
|
40
|
-
raise ActiveRecord::StatementInvalid.new("Could not find schema #{tenant}") unless Apartment.connection.all_schemas.include? tenant.to_s
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
tenant = tenant.to_s
|
|
42
|
+
raise ActiveRecord::StatementInvalid, "Could not find schema #{tenant}" unless tenant_exists?(tenant)
|
|
44
43
|
|
|
44
|
+
@current = tenant
|
|
45
|
+
Apartment.connection.schema_search_path = full_search_path
|
|
45
46
|
rescue ActiveRecord::StatementInvalid, ActiveRecord::JDBCError
|
|
46
47
|
raise TenantNotFound, "One of the following schema(s) is invalid: #{full_search_path}"
|
|
47
48
|
end
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def tenant_exists?(tenant)
|
|
53
|
+
return true unless Apartment.tenant_presence_check
|
|
54
|
+
|
|
55
|
+
Apartment.connection.all_schemas.include? tenant
|
|
56
|
+
end
|
|
50
57
|
|
|
51
58
|
def rescue_from
|
|
52
59
|
ActiveRecord::JDBCError
|
|
@@ -1,25 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'apartment/adapters/abstract_adapter'
|
|
2
4
|
|
|
3
5
|
module Apartment
|
|
4
6
|
module Tenant
|
|
5
|
-
|
|
6
7
|
def self.mysql2_adapter(config)
|
|
7
|
-
Apartment.use_schemas
|
|
8
|
-
Adapters::Mysql2SchemaAdapter.new(config)
|
|
8
|
+
if Apartment.use_schemas
|
|
9
|
+
Adapters::Mysql2SchemaAdapter.new(config)
|
|
10
|
+
else
|
|
9
11
|
Adapters::Mysql2Adapter.new(config)
|
|
12
|
+
end
|
|
10
13
|
end
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
module Adapters
|
|
14
17
|
class Mysql2Adapter < AbstractAdapter
|
|
15
|
-
|
|
16
18
|
def initialize(config)
|
|
17
19
|
super
|
|
18
20
|
|
|
19
21
|
@default_tenant = config[:database]
|
|
20
22
|
end
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
protected
|
|
23
25
|
|
|
24
26
|
def rescue_from
|
|
25
27
|
Mysql2::Error
|
|
@@ -40,7 +42,7 @@ module Apartment
|
|
|
40
42
|
Apartment.connection.execute "use `#{default_tenant}`"
|
|
41
43
|
end
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
protected
|
|
44
46
|
|
|
45
47
|
# Connect to new tenant
|
|
46
48
|
#
|
|
@@ -48,10 +50,9 @@ module Apartment
|
|
|
48
50
|
return reset if tenant.nil?
|
|
49
51
|
|
|
50
52
|
Apartment.connection.execute "use `#{environmentify(tenant)}`"
|
|
51
|
-
|
|
52
|
-
rescue ActiveRecord::StatementInvalid => exception
|
|
53
|
+
rescue ActiveRecord::StatementInvalid => e
|
|
53
54
|
Apartment::Tenant.reset
|
|
54
|
-
raise_connect_error!(tenant,
|
|
55
|
+
raise_connect_error!(tenant, e)
|
|
55
56
|
end
|
|
56
57
|
|
|
57
58
|
def process_excluded_model(model)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# handle postgis adapter as if it were postgresql,
|
|
2
4
|
# only override the adapter_method used for initialization
|
|
3
|
-
require
|
|
5
|
+
require 'apartment/adapters/postgresql_adapter'
|
|
4
6
|
|
|
5
7
|
module Apartment
|
|
6
8
|
module Tenant
|
|
7
|
-
|
|
8
9
|
def self.postgis_adapter(config)
|
|
9
10
|
postgresql_adapter(config)
|
|
10
11
|
end
|