ros-apartment 2.3.0 → 2.7.0

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