ros-apartment 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/.rubocop-linter.yml +22 -0
  3. data/.pryrc +5 -3
  4. data/.rubocop.yml +17 -0
  5. data/.rubocop_todo.yml +29 -0
  6. data/.story_branch.yml +4 -0
  7. data/.travis.yml +12 -11
  8. data/Appraisals +18 -18
  9. data/Gemfile +4 -1
  10. data/README.md +33 -5
  11. data/Rakefile +2 -0
  12. data/apartment.gemspec +6 -6
  13. data/gemfiles/rails_4_2.gemfile +12 -10
  14. data/gemfiles/rails_5_0.gemfile +11 -9
  15. data/gemfiles/rails_5_1.gemfile +11 -9
  16. data/gemfiles/rails_5_2.gemfile +10 -8
  17. data/gemfiles/rails_6_0.gemfile +11 -9
  18. data/gemfiles/rails_master.gemfile +11 -9
  19. data/lib/apartment/adapters/abstract_adapter.rb +34 -34
  20. data/lib/apartment/adapters/abstract_jdbc_adapter.rb +4 -3
  21. data/lib/apartment/adapters/jdbc_mysql_adapter.rb +3 -3
  22. data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +13 -11
  23. data/lib/apartment/adapters/mysql2_adapter.rb +10 -9
  24. data/lib/apartment/adapters/postgis_adapter.rb +3 -2
  25. data/lib/apartment/adapters/postgresql_adapter.rb +28 -25
  26. data/lib/apartment/adapters/sqlite3_adapter.rb +16 -8
  27. data/lib/apartment/console.rb +28 -3
  28. data/lib/apartment/custom_console.rb +26 -0
  29. data/lib/apartment/deprecation.rb +2 -1
  30. data/lib/apartment/elevators/domain.rb +4 -3
  31. data/lib/apartment/elevators/first_subdomain.rb +3 -2
  32. data/lib/apartment/elevators/generic.rb +4 -3
  33. data/lib/apartment/elevators/host.rb +6 -1
  34. data/lib/apartment/elevators/host_hash.rb +6 -2
  35. data/lib/apartment/elevators/subdomain.rb +9 -5
  36. data/lib/apartment/migrator.rb +4 -3
  37. data/lib/apartment/railtie.rb +13 -5
  38. data/lib/apartment/reloader.rb +2 -1
  39. data/lib/apartment/tasks/enhancements.rb +4 -6
  40. data/lib/apartment/tenant.rb +3 -4
  41. data/lib/apartment/version.rb +3 -1
  42. data/lib/apartment.rb +15 -9
  43. data/lib/generators/apartment/install/install_generator.rb +4 -3
  44. data/lib/generators/apartment/install/templates/apartment.rb +3 -2
  45. data/lib/tasks/apartment.rake +19 -18
  46. data/spec/adapters/jdbc_mysql_adapter_spec.rb +5 -4
  47. data/spec/adapters/jdbc_postgresql_adapter_spec.rb +10 -12
  48. data/spec/adapters/mysql2_adapter_spec.rb +15 -13
  49. data/spec/adapters/postgresql_adapter_spec.rb +22 -20
  50. data/spec/adapters/sqlite3_adapter_spec.rb +41 -23
  51. data/spec/apartment_spec.rb +4 -2
  52. data/spec/dummy/app/controllers/application_controller.rb +4 -3
  53. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  54. data/spec/dummy/app/models/application_record.rb +6 -0
  55. data/spec/dummy/app/models/company.rb +4 -2
  56. data/spec/dummy/app/models/user.rb +4 -2
  57. data/spec/dummy/config/application.rb +11 -9
  58. data/spec/dummy/config/boot.rb +4 -2
  59. data/spec/dummy/config/environment.rb +3 -1
  60. data/spec/dummy/config/environments/development.rb +2 -1
  61. data/spec/dummy/config/environments/production.rb +3 -1
  62. data/spec/dummy/config/environments/test.rb +3 -1
  63. data/spec/dummy/config/initializers/apartment.rb +4 -2
  64. data/spec/dummy/config/initializers/backtrace_silencers.rb +1 -0
  65. data/spec/dummy/config/initializers/inflections.rb +1 -0
  66. data/spec/dummy/config/initializers/mime_types.rb +1 -0
  67. data/spec/dummy/config/initializers/secret_token.rb +2 -0
  68. data/spec/dummy/config/initializers/session_store.rb +3 -1
  69. data/spec/dummy/config/routes.rb +3 -1
  70. data/spec/dummy/config.ru +3 -1
  71. data/spec/dummy/db/seeds/import.rb +3 -1
  72. data/spec/dummy/script/rails +4 -2
  73. data/spec/dummy_engine/config/initializers/apartment.rb +4 -3
  74. data/spec/dummy_engine/lib/dummy_engine/engine.rb +2 -0
  75. data/spec/dummy_engine/lib/dummy_engine/version.rb +3 -1
  76. data/spec/dummy_engine/lib/dummy_engine.rb +3 -1
  77. data/spec/dummy_engine/test/dummy/config/application.rb +4 -2
  78. data/spec/dummy_engine/test/dummy/config/boot.rb +4 -2
  79. data/spec/dummy_engine/test/dummy/config/environment.rb +3 -1
  80. data/spec/dummy_engine/test/dummy/config/environments/development.rb +2 -0
  81. data/spec/dummy_engine/test/dummy/config/environments/production.rb +2 -0
  82. data/spec/dummy_engine/test/dummy/config/environments/test.rb +2 -0
  83. data/spec/dummy_engine/test/dummy/config/initializers/assets.rb +2 -0
  84. data/spec/dummy_engine/test/dummy/config/initializers/backtrace_silencers.rb +1 -0
  85. data/spec/dummy_engine/test/dummy/config/initializers/cookies_serializer.rb +3 -1
  86. data/spec/dummy_engine/test/dummy/config/initializers/filter_parameter_logging.rb +2 -0
  87. data/spec/dummy_engine/test/dummy/config/initializers/inflections.rb +1 -0
  88. data/spec/dummy_engine/test/dummy/config/initializers/mime_types.rb +1 -0
  89. data/spec/dummy_engine/test/dummy/config/initializers/session_store.rb +2 -0
  90. data/spec/dummy_engine/test/dummy/config/initializers/wrap_parameters.rb +2 -0
  91. data/spec/dummy_engine/test/dummy/config/routes.rb +2 -0
  92. data/spec/dummy_engine/test/dummy/config.ru +3 -1
  93. data/spec/examples/connection_adapter_examples.rb +15 -13
  94. data/spec/examples/generic_adapter_custom_configuration_example.rb +21 -23
  95. data/spec/examples/generic_adapter_examples.rb +40 -39
  96. data/spec/examples/schema_adapter_examples.rb +93 -88
  97. data/spec/integration/apartment_rake_integration_spec.rb +24 -24
  98. data/spec/integration/query_caching_spec.rb +10 -8
  99. data/spec/integration/use_within_an_engine_spec.rb +5 -5
  100. data/spec/schemas/v1.rb +2 -3
  101. data/spec/schemas/v2.rb +22 -24
  102. data/spec/schemas/v3.rb +26 -28
  103. data/spec/spec_helper.rb +8 -6
  104. data/spec/support/apartment_helpers.rb +9 -5
  105. data/spec/support/capybara_sessions.rb +5 -5
  106. data/spec/support/config.rb +5 -2
  107. data/spec/support/contexts.rb +10 -8
  108. data/spec/support/requirements.rb +19 -6
  109. data/spec/support/setup.rb +5 -5
  110. data/spec/tasks/apartment_rake_spec.rb +30 -35
  111. data/spec/tenant_spec.rb +48 -44
  112. data/spec/unit/config_spec.rb +26 -27
  113. data/spec/unit/elevators/domain_spec.rb +9 -8
  114. data/spec/unit/elevators/first_subdomain_spec.rb +14 -12
  115. data/spec/unit/elevators/generic_spec.rb +16 -15
  116. data/spec/unit/elevators/host_hash_spec.rb +9 -8
  117. data/spec/unit/elevators/host_spec.rb +26 -26
  118. data/spec/unit/elevators/subdomain_spec.rb +24 -23
  119. data/spec/unit/migrator_spec.rb +18 -17
  120. data/spec/unit/reloader_spec.rb +8 -8
  121. metadata +40 -22
@@ -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
@@ -45,7 +48,7 @@ module Apartment
45
48
  def default_tenant
46
49
  @default_tenant || Apartment.default_tenant
47
50
  end
48
- alias :default_schema :default_tenant # TODO deprecate default_schema
51
+ alias default_schema default_tenant # TODO: deprecate default_schema
49
52
 
50
53
  # Drop the tenant
51
54
  #
@@ -55,9 +58,8 @@ module Apartment
55
58
  with_neutral_connection(tenant) do |conn|
56
59
  drop_command(conn, tenant)
57
60
  end
58
-
59
- rescue *rescuable_exceptions => exception
60
- raise_drop_tenant_error!(tenant, exception)
61
+ rescue *rescuable_exceptions => e
62
+ raise_drop_tenant_error!(tenant, e)
61
63
  end
62
64
 
63
65
  # Switch to a new tenant
@@ -79,13 +81,14 @@ module Apartment
79
81
  # @param {String?} tenant to connect to
80
82
  #
81
83
  def switch(tenant = nil)
84
+ previous_tenant = current
85
+ switch!(tenant)
86
+ yield
87
+ ensure
82
88
  begin
83
- previous_tenant = current
84
- switch!(tenant)
85
- yield
86
-
87
- ensure
88
- switch!(previous_tenant) rescue reset
89
+ switch!(previous_tenant)
90
+ rescue StandardError => _e
91
+ reset
89
92
  end
90
93
  end
91
94
 
@@ -93,7 +96,7 @@ module Apartment
93
96
  #
94
97
  def each(tenants = Apartment.tenant_names)
95
98
  tenants.each do |tenant|
96
- switch(tenant){ yield tenant }
99
+ switch(tenant) { yield tenant }
97
100
  end
98
101
  end
99
102
 
@@ -116,9 +119,9 @@ module Apartment
116
119
  #
117
120
  def seed_data
118
121
  # Don't log the output of seeding the db
119
- silence_warnings{ load_or_raise(Apartment.seed_data_file) } if Apartment.seed_data_file
122
+ silence_warnings { load_or_raise(Apartment.seed_data_file) } if Apartment.seed_data_file
120
123
  end
121
- alias_method :seed, :seed_data
124
+ alias seed seed_data
122
125
 
123
126
  # Prepend the environment if configured and the environment isn't already there
124
127
  #
@@ -126,7 +129,7 @@ module Apartment
126
129
  # @return {String} tenant name with Rails environment *optionally* prepended
127
130
  #
128
131
  def environmentify(tenant)
129
- unless tenant.include?(Rails.env)
132
+ if !tenant.include?(Rails.env)
130
133
  if Apartment.prepend_environment
131
134
  "#{Rails.env}_#{tenant}"
132
135
  elsif Apartment.append_environment
@@ -139,7 +142,7 @@ module Apartment
139
142
  end
140
143
  end
141
144
 
142
- protected
145
+ protected
143
146
 
144
147
  def process_excluded_model(excluded_model)
145
148
  excluded_model.constantize.establish_connection @config
@@ -158,8 +161,8 @@ module Apartment
158
161
  with_neutral_connection(tenant) do |conn|
159
162
  create_tenant_command(conn, tenant)
160
163
  end
161
- rescue *rescuable_exceptions => exception
162
- raise_create_tenant_error!(tenant, exception)
164
+ rescue *rescuable_exceptions => e
165
+ raise_create_tenant_error!(tenant, e)
163
166
  end
164
167
 
165
168
  def create_tenant_command(conn, tenant)
@@ -174,18 +177,18 @@ module Apartment
174
177
  query_cache_enabled = ActiveRecord::Base.connection.query_cache_enabled
175
178
 
176
179
  Apartment.establish_connection multi_tenantify(tenant)
177
- Apartment.connection.active? # call active? to manually check if this connection is valid
180
+ Apartment.connection.active? # call active? to manually check if this connection is valid
178
181
 
179
182
  Apartment.connection.enable_query_cache! if query_cache_enabled
180
- rescue *rescuable_exceptions => exception
183
+ rescue *rescuable_exceptions => e
181
184
  Apartment::Tenant.reset if reset_on_connection_exception?
182
- raise_connect_error!(tenant, exception)
185
+ raise_connect_error!(tenant, e)
183
186
  end
184
187
 
185
188
  # Import the database schema
186
189
  #
187
190
  def import_database_schema
188
- ActiveRecord::Schema.verbose = false # do not log schema load output.
191
+ ActiveRecord::Schema.verbose = false # do not log schema load output.
189
192
 
190
193
  load_or_raise(Apartment.database_schema_file) if Apartment.database_schema_file
191
194
  end
@@ -196,9 +199,7 @@ module Apartment
196
199
  # if false, use the default db name from the db
197
200
  def multi_tenantify(tenant, with_database = true)
198
201
  db_connection_config(tenant).tap do |config|
199
- if with_database
200
- multi_tenantify_with_tenant_db_name(config, tenant)
201
- end
202
+ multi_tenantify_with_tenant_db_name(config, tenant) if with_database
202
203
  end
203
204
  end
204
205
 
@@ -209,14 +210,12 @@ module Apartment
209
210
  # Load a file or raise error if it doesn't exists
210
211
  #
211
212
  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
213
+ raise FileNotFound, "#{file} doesn't exist yet" unless File.exist?(file)
214
+
215
+ load(file)
217
216
  end
218
217
  # Backward compatibility
219
- alias_method :load_or_abort, :load_or_raise
218
+ alias load_or_abort load_or_raise
220
219
 
221
220
  # Exceptions to rescue from on db operations
222
221
  #
@@ -234,7 +233,7 @@ module Apartment
234
233
  Apartment.db_config_for(tenant).clone
235
234
  end
236
235
 
237
- def with_neutral_connection(tenant, &block)
236
+ def with_neutral_connection(tenant, &_block)
238
237
  if Apartment.with_multi_server_setup
239
238
  # neutral connection is necessary whenever you need to create/remove a database from a server.
240
239
  # example: when you use postgresql, you need to connect to the default postgresql database before you create your own.
@@ -251,19 +250,20 @@ module Apartment
251
250
  end
252
251
 
253
252
  def raise_drop_tenant_error!(tenant, exception)
254
- raise TenantNotFound, "Error while dropping tenant #{environmentify(tenant)}: #{ exception.message }"
253
+ raise TenantNotFound, "Error while dropping tenant #{environmentify(tenant)}: #{exception.message}"
255
254
  end
256
255
 
257
256
  def raise_create_tenant_error!(tenant, exception)
258
- raise TenantExists, "Error while creating tenant #{environmentify(tenant)}: #{ exception.message }"
257
+ raise TenantExists, "Error while creating tenant #{environmentify(tenant)}: #{exception.message}"
259
258
  end
260
259
 
261
260
  def raise_connect_error!(tenant, exception)
262
- raise TenantNotFound, "Error while connecting to tenant #{environmentify(tenant)}: #{ exception.message }"
261
+ raise TenantNotFound, "Error while connecting to tenant #{environmentify(tenant)}: #{exception.message}"
263
262
  end
264
263
 
265
264
  class SeparateDbConnectionHandler < ::ActiveRecord::Base
266
265
  end
267
266
  end
268
267
  end
268
+ # rubocop:enable Metrics/ClassLength
269
269
  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,22 @@ 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
+ # rubocop:disable Style/RaiseArgs
40
41
  raise ActiveRecord::StatementInvalid.new("Could not find schema #{tenant}") unless Apartment.connection.all_schemas.include? tenant.to_s
41
42
 
43
+ # rubocop:enable Style/RaiseArgs
44
+
42
45
  @current = tenant.to_s
43
46
  Apartment.connection.schema_search_path = full_search_path
44
-
45
47
  rescue ActiveRecord::StatementInvalid, ActiveRecord::JDBCError
46
48
  raise TenantNotFound, "One of the following schema(s) is invalid: #{full_search_path}"
47
49
  end
48
50
 
49
- private
51
+ private
50
52
 
51
53
  def rescue_from
52
54
  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
@@ -40,7 +42,7 @@ module Apartment
40
42
  Apartment.connection.execute "use `#{default_tenant}`"
41
43
  end
42
44
 
43
- protected
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, exception)
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 "apartment/adapters/postgresql_adapter"
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
@@ -1,8 +1,9 @@
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.postgresql_adapter(config)
7
8
  adapter = Adapters::PostgresqlAdapter
8
9
  adapter = Adapters::PostgresqlSchemaAdapter if Apartment.use_schemas
@@ -14,8 +15,7 @@ module Apartment
14
15
  module Adapters
15
16
  # Default adapter when not using Postgresql Schemas
16
17
  class PostgresqlAdapter < AbstractAdapter
17
-
18
- private
18
+ private
19
19
 
20
20
  def rescue_from
21
21
  PG::Error
@@ -24,7 +24,6 @@ module Apartment
24
24
 
25
25
  # Separate Adapter for Postgresql when using schemas
26
26
  class PostgresqlSchemaAdapter < AbstractAdapter
27
-
28
27
  def initialize(config)
29
28
  super
30
29
 
@@ -44,7 +43,7 @@ module Apartment
44
43
  @current || default_tenant
45
44
  end
46
45
 
47
- protected
46
+ protected
48
47
 
49
48
  def process_excluded_model(excluded_model)
50
49
  excluded_model.constantize.tap do |klass|
@@ -56,39 +55,39 @@ module Apartment
56
55
  end
57
56
 
58
57
  def drop_command(conn, tenant)
59
- conn.execute(%{DROP SCHEMA "#{tenant}" CASCADE})
58
+ conn.execute(%(DROP SCHEMA "#{tenant}" CASCADE))
60
59
  end
61
60
 
62
61
  # Set schema search path to new schema
63
62
  #
64
63
  def connect_to_new(tenant = nil)
65
64
  return reset if tenant.nil?
65
+ # rubocop:disable Style/RaiseArgs
66
66
  raise ActiveRecord::StatementInvalid.new("Could not find schema #{tenant}") unless Apartment.connection.schema_exists?(tenant.to_s)
67
67
 
68
+ # rubocop:enable Style/RaiseArgs
69
+
68
70
  @current = tenant.to_s
69
71
  Apartment.connection.schema_search_path = full_search_path
70
72
 
71
73
  # When the PostgreSQL version is < 9.3,
72
74
  # there is a issue for prepared statement with changing search_path.
73
75
  # https://www.postgresql.org/docs/9.3/static/sql-prepare.html
74
- if postgresql_version < 90300
75
- Apartment.connection.clear_cache!
76
- end
77
-
76
+ Apartment.connection.clear_cache! if postgresql_version < 90_300
78
77
  rescue *rescuable_exceptions
79
78
  raise TenantNotFound, "One of the following schema(s) is invalid: \"#{tenant}\" #{full_search_path}"
80
79
  end
81
80
 
82
- private
81
+ private
83
82
 
84
83
  def create_tenant_command(conn, tenant)
85
- conn.execute(%{CREATE SCHEMA "#{tenant}"})
84
+ conn.execute(%(CREATE SCHEMA "#{tenant}"))
86
85
  end
87
86
 
88
87
  # Generate the final search path to set including persistent_schemas
89
88
  #
90
89
  def full_search_path
91
- persistent_schemas.map(&:inspect).join(", ")
90
+ persistent_schemas.map(&:inspect).join(', ')
92
91
  end
93
92
 
94
93
  def persistent_schemas
@@ -104,16 +103,15 @@ module Apartment
104
103
 
105
104
  # Another Adapter for Postgresql when using schemas and SQL
106
105
  class PostgresqlSchemaFromSqlAdapter < PostgresqlSchemaAdapter
107
-
108
- PSQL_DUMP_BLACKLISTED_STATEMENTS= [
106
+ PSQL_DUMP_BLACKLISTED_STATEMENTS = [
109
107
  /SET search_path/i, # overridden later
110
108
  /SET lock_timeout/i, # new in postgresql 9.3
111
109
  /SET row_security/i, # new in postgresql 9.5
112
110
  /SET idle_in_transaction_session_timeout/i, # new in postgresql 9.6
113
111
  /CREATE SCHEMA public/i,
114
- /COMMENT ON SCHEMA public/i,
112
+ /COMMENT ON SCHEMA public/i
115
113
 
116
- ]
114
+ ].freeze
117
115
 
118
116
  def import_database_schema
119
117
  preserving_search_path do
@@ -122,14 +120,14 @@ module Apartment
122
120
  end
123
121
  end
124
122
 
125
- private
123
+ private
126
124
 
127
125
  # Re-set search path after the schema is imported.
128
126
  # Postgres now sets search path to empty before dumping the schema
129
127
  # and it mut be reset
130
128
  #
131
129
  def preserving_search_path
132
- search_path = Apartment.connection.execute("show search_path").first["search_path"]
130
+ search_path = Apartment.connection.execute('show search_path').first['search_path']
133
131
  yield
134
132
  Apartment.connection.execute("set search_path = #{search_path}")
135
133
  end
@@ -153,7 +151,6 @@ module Apartment
153
151
  # @return {String} raw SQL contaning only postgres schema dump
154
152
  #
155
153
  def pg_dump_schema
156
-
157
154
  # Skip excluded tables? :/
158
155
  # excluded_tables =
159
156
  # collect_table_names(Apartment.excluded_models)
@@ -176,7 +173,10 @@ module Apartment
176
173
  # Temporary set Postgresql related environment variables if there are in @config
177
174
  #
178
175
  def with_pg_env(&block)
179
- pghost, pgport, pguser, pgpassword = ENV['PGHOST'], ENV['PGPORT'], ENV['PGUSER'], ENV['PGPASSWORD']
176
+ pghost = ENV['PGHOST']
177
+ pgport = ENV['PGPORT']
178
+ pguser = ENV['PGUSER']
179
+ pgpassword = ENV['PGPASSWORD']
180
180
 
181
181
  ENV['PGHOST'] = @config[:host] if @config[:host]
182
182
  ENV['PGPORT'] = @config[:port].to_s if @config[:port]
@@ -185,7 +185,10 @@ module Apartment
185
185
 
186
186
  block.call
187
187
  ensure
188
- ENV['PGHOST'], ENV['PGPORT'], ENV['PGUSER'], ENV['PGPASSWORD'] = pghost, pgport, pguser, pgpassword
188
+ ENV['PGHOST'] = pghost
189
+ ENV['PGPORT'] = pgport
190
+ ENV['PGUSER'] = pguser
191
+ ENV['PGPASSWORD'] = pgpassword
189
192
  end
190
193
 
191
194
  # Remove "SET search_path ..." line from SQL dump and prepend search_path set to current tenant
@@ -197,7 +200,7 @@ module Apartment
197
200
 
198
201
  swap_schema_qualifier(sql)
199
202
  .split("\n")
200
- .select {|line| check_input_against_regexps(line, PSQL_DUMP_BLACKLISTED_STATEMENTS).empty?}
203
+ .select { |line| check_input_against_regexps(line, PSQL_DUMP_BLACKLISTED_STATEMENTS).empty? }
201
204
  .prepend(search_path)
202
205
  .join("\n")
203
206
  end
@@ -207,7 +210,7 @@ module Apartment
207
210
  if Apartment.pg_excluded_names.any? { |name| match.include? name }
208
211
  match
209
212
  else
210
- match.gsub("#{default_tenant}.", %{"#{current}".})
213
+ match.gsub("#{default_tenant}.", %("#{current}".))
211
214
  end
212
215
  end
213
216
  end
@@ -215,7 +218,7 @@ module Apartment
215
218
  # Checks if any of regexps matches against input
216
219
  #
217
220
  def check_input_against_regexps(input, regexps)
218
- regexps.select {|c| input.match c}
221
+ regexps.select { |c| input.match c }
219
222
  end
220
223
 
221
224
  # Collect table names from AR Models
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'apartment/adapters/abstract_adapter'
2
4
 
3
5
  module Apartment
@@ -16,8 +18,10 @@ module Apartment
16
18
  end
17
19
 
18
20
  def drop(tenant)
19
- raise TenantNotFound,
20
- "The tenant #{environmentify(tenant)} cannot be found." unless File.exists?(database_file(tenant))
21
+ unless File.exist?(database_file(tenant))
22
+ raise TenantNotFound,
23
+ "The tenant #{environmentify(tenant)} cannot be found."
24
+ end
21
25
 
22
26
  File.delete(database_file(tenant))
23
27
  end
@@ -26,18 +30,22 @@ module Apartment
26
30
  File.basename(Apartment.connection.instance_variable_get(:@config)[:database], '.sqlite3')
27
31
  end
28
32
 
29
- protected
33
+ protected
30
34
 
31
35
  def connect_to_new(tenant)
32
- raise TenantNotFound,
33
- "The tenant #{environmentify(tenant)} cannot be found." unless File.exists?(database_file(tenant))
36
+ unless File.exist?(database_file(tenant))
37
+ raise TenantNotFound,
38
+ "The tenant #{environmentify(tenant)} cannot be found."
39
+ end
34
40
 
35
41
  super database_file(tenant)
36
42
  end
37
43
 
38
44
  def create_tenant(tenant)
39
- raise TenantExists,
40
- "The tenant #{environmentify(tenant)} already exists." if File.exists?(database_file(tenant))
45
+ if File.exist?(database_file(tenant))
46
+ raise TenantExists,
47
+ "The tenant #{environmentify(tenant)} already exists."
48
+ end
41
49
 
42
50
  begin
43
51
  f = File.new(database_file(tenant), File::CREAT)
@@ -46,7 +54,7 @@ module Apartment
46
54
  end
47
55
  end
48
56
 
49
- private
57
+ private
50
58
 
51
59
  def database_file(tenant)
52
60
  "#{@default_dir}/#{environmentify(tenant)}.sqlite3"
@@ -1,12 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # A workaraound to get `reload!` to also call Apartment::Tenant.init
2
4
  # This is unfortunate, but I haven't figured out how to hook into the reload process *after* files are reloaded
3
5
 
4
6
  # reloads the environment
5
- def reload!(print=true)
6
- puts "Reloading..." if print
7
+ def reload!(print = true)
8
+ # rubocop:disable Rails/Output
9
+ puts 'Reloading...' if print
10
+ # rubocop:enable Rails/Output
11
+
7
12
  # This triggers the to_prepare callbacks
8
- ActionDispatch::Callbacks.new(Proc.new {}).call({})
13
+ ActionDispatch::Callbacks.new(proc {}).call({})
9
14
  # Manually init Apartment again once classes are reloaded
10
15
  Apartment::Tenant.init
11
16
  true
12
17
  end
18
+
19
+ def st(schema_name = nil)
20
+ if schema_name.nil?
21
+ # rubocop:disable Rails/Output
22
+ tenant_list.each { |t| puts t }
23
+ # rubocop:enable Rails/Output
24
+ elsif tenant_list.include? schema_name
25
+ Apartment::Tenant.switch!(schema_name)
26
+ else
27
+ # rubocop:disable Rails/Output
28
+ puts "Tenant #{schema_name} is not part of the tenant list"
29
+ # rubocop:enable Rails/Output
30
+ end
31
+ end
32
+
33
+ def tenant_list
34
+ tenant_list = [Apartment.default_tenant]
35
+ tenant_list += Apartment.tenant_names
36
+ tenant_list.uniq
37
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apartment
4
+ module CustomConsole
5
+ begin
6
+ require 'pry-rails'
7
+ rescue LoadError
8
+ # rubocop:disable Rails/Output
9
+ puts '[Failed to load pry-rails] If you want to use Apartment custom prompt you need to add pry-rails to your gemfile'
10
+ # rubocop:enable Rails/Output
11
+ end
12
+
13
+ if Pry::Prompt.respond_to?(:add)
14
+ desc = "Includes the current Rails environment and project folder name.\n" \
15
+ '[1] [project_name][Rails.env][Apartment::Tenant.current] pry(main)>'
16
+
17
+ Pry::Prompt.add 'ros', desc, %w[> *] do |target_self, nest_level, pry, sep|
18
+ "[#{pry.input_ring.size}] [#{PryRails::Prompt.formatted_env}][#{Apartment::Tenant.current}] " \
19
+ "#{pry.config.prompt_name}(#{Pry.view_clip(target_self)})" \
20
+ "#{":#{nest_level}" unless nest_level.zero?}#{sep} "
21
+ end
22
+
23
+ Pry.config.prompt = Pry::Prompt[:ros][:value]
24
+ end
25
+ end
26
+ end
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/deprecation'
2
4
 
3
5
  module Apartment
4
6
  module Deprecation
5
-
6
7
  def self.warn(message)
7
8
  ActiveSupport::Deprecation.warn message
8
9
  end