ros-apartment 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,23 +12,38 @@ module Apartment::PostgreSqlAdapterPatch
12
12
  # for JDBC driver, if rescued in super_method, trim leading and trailing quotes
13
13
  res.delete!('"') if defined?(JRUBY_VERSION)
14
14
 
15
- schema_prefix = "#{Apartment::Tenant.current}."
16
- default_tenant_prefix = "#{Apartment::Tenant.default_tenant}."
15
+ schema_prefix = "#{sequence_schema(res)}."
17
16
 
18
17
  # NOTE: Excluded models should always access the sequence from the default
19
18
  # tenant schema
20
19
  if excluded_model?(table)
21
- res.sub!(schema_prefix, default_tenant_prefix) if schema_prefix != default_tenant_prefix
20
+ default_tenant_prefix = "#{Apartment::Tenant.default_tenant}."
21
+
22
+ # Unless the res is already prefixed with the default_tenant_prefix
23
+ # we should delete the schema_prefix and add the default_tenant_prefix
24
+ unless res&.starts_with?(default_tenant_prefix)
25
+ res&.delete_prefix!(schema_prefix)
26
+ res = default_tenant_prefix + res
27
+ end
28
+
22
29
  return res
23
30
  end
24
31
 
25
- res.delete_prefix!(schema_prefix) if res&.starts_with?(schema_prefix)
32
+ # Delete the schema_prefix from the res if it is present
33
+ res&.delete_prefix!(schema_prefix)
26
34
 
27
35
  res
28
36
  end
29
37
 
30
38
  private
31
39
 
40
+ def sequence_schema(sequence_name)
41
+ current = Apartment::Tenant.current
42
+ return current unless current.is_a?(Array)
43
+
44
+ current.find { |schema| sequence_name.starts_with?("#{schema}.") }
45
+ end
46
+
32
47
  def excluded_model?(table)
33
48
  Apartment.excluded_models.any? { |m| m.constantize.table_name == table }
34
49
  end
@@ -181,7 +181,7 @@ module Apartment
181
181
  query_cache_enabled = ActiveRecord::Base.connection.query_cache_enabled
182
182
 
183
183
  Apartment.establish_connection multi_tenantify(tenant)
184
- Apartment.connection.active? # call active? to manually check if this connection is valid
184
+ Apartment.connection.verify! # call active? to manually check if this connection is valid
185
185
 
186
186
  Apartment.connection.enable_query_cache! if query_cache_enabled
187
187
  rescue *rescuable_exceptions => e
@@ -76,11 +76,6 @@ module Apartment
76
76
 
77
77
  @current = tenant.is_a?(Array) ? tenant.map(&:to_s) : tenant.to_s
78
78
  Apartment.connection.schema_search_path = full_search_path
79
-
80
- # When the PostgreSQL version is < 9.3,
81
- # there is a issue for prepared statement with changing search_path.
82
- # https://www.postgresql.org/docs/9.3/static/sql-prepare.html
83
- Apartment.connection.clear_cache! if postgresql_version < 90_300
84
79
  rescue *rescuable_exceptions => e
85
80
  raise_schema_connect_to_new(tenant, e)
86
81
  end
@@ -151,8 +146,9 @@ module Apartment
151
146
  /SET row_security/i, # new in postgresql 9.5
152
147
  /SET idle_in_transaction_session_timeout/i, # new in postgresql 9.6
153
148
  /SET default_table_access_method/i, # new in postgresql 12
154
- /CREATE SCHEMA public/i,
155
- /COMMENT ON SCHEMA public/i
149
+ /CREATE SCHEMA/i,
150
+ /COMMENT ON SCHEMA/i,
151
+ /SET transaction_timeout/i, # new in postgresql 17
156
152
 
157
153
  ].freeze
158
154
 
@@ -194,15 +190,13 @@ module Apartment
194
190
  # @return {String} raw SQL contaning only postgres schema dump
195
191
  #
196
192
  def pg_dump_schema
197
- # Skip excluded tables? :/
198
- # excluded_tables =
199
- # collect_table_names(Apartment.excluded_models)
200
- # .map! {|t| "-T #{t}"}
201
- # .join(' ')
202
-
203
- # `pg_dump -s -x -O -n #{default_tenant} #{excluded_tables} #{dbname}`
204
-
205
- with_pg_env { `pg_dump -s -x -O -n #{default_tenant} #{dbname}` }
193
+ exclude_table =
194
+ if Apartment.pg_exclude_clone_tables
195
+ excluded_tables.map! { |t| "-T #{t}" }.join(' ')
196
+ else
197
+ ''
198
+ end
199
+ with_pg_env { `pg_dump -s -x -O -n #{default_tenant} #{dbname} #{exclude_table}` }
206
200
  end
207
201
 
208
202
  # Dump data from schema_migrations table
@@ -254,6 +248,8 @@ module Apartment
254
248
  sql.gsub(/#{default_tenant}\.\w*/) do |match|
255
249
  if Apartment.pg_excluded_names.any? { |name| match.include? name }
256
250
  match
251
+ elsif Apartment.pg_exclude_clone_tables && excluded_tables.any?(match)
252
+ match
257
253
  else
258
254
  match.gsub("#{default_tenant}.", %("#{current}".))
259
255
  end
@@ -266,10 +262,10 @@ module Apartment
266
262
  regexps.select { |c| input.match c }
267
263
  end
268
264
 
269
- # Collect table names from AR Models
265
+ # Convenience method for excluded table names
270
266
  #
271
- def collect_table_names(models)
272
- models.map do |m|
267
+ def excluded_tables
268
+ Apartment.excluded_models.map do |m|
273
269
  m.constantize.table_name
274
270
  end
275
271
  end
@@ -1,11 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_support/deprecation'
4
+ require_relative 'version'
4
5
 
5
6
  module Apartment
6
- module Deprecation
7
- def self.warn(message)
8
- ActiveSupport::Deprecation.warn message
9
- end
10
- end
7
+ DEPRECATOR = ActiveSupport::Deprecation.new(Apartment::VERSION, 'Apartment')
11
8
  end
@@ -13,21 +13,33 @@ module Apartment
13
13
 
14
14
  migration_scope_block = ->(migration) { ENV['SCOPE'].blank? || (ENV['SCOPE'] == migration.scope) }
15
15
 
16
- ActiveRecord::Base.connection.migration_context.migrate(version, &migration_scope_block)
16
+ if ActiveRecord.version >= Gem::Version.new('7.2.0')
17
+ ActiveRecord::Base.connection_pool.migration_context.migrate(version, &migration_scope_block)
18
+ else
19
+ ActiveRecord::Base.connection.migration_context.migrate(version, &migration_scope_block)
20
+ end
17
21
  end
18
22
  end
19
23
 
20
24
  # Migrate up/down to a specific version
21
25
  def run(direction, database, version)
22
26
  Tenant.switch(database) do
23
- ActiveRecord::Base.connection.migration_context.run(direction, version)
27
+ if ActiveRecord.version >= Gem::Version.new('7.2.0')
28
+ ActiveRecord::Base.connection_pool.migration_context.run(direction, version)
29
+ else
30
+ ActiveRecord::Base.connection.migration_context.run(direction, version)
31
+ end
24
32
  end
25
33
  end
26
34
 
27
35
  # rollback latest migration `step` number of times
28
36
  def rollback(database, step = 1)
29
37
  Tenant.switch(database) do
30
- ActiveRecord::Base.connection.migration_context.rollback(step)
38
+ if ActiveRecord.version >= Gem::Version.new('7.2.0')
39
+ ActiveRecord::Base.connection_pool.migration_context.rollback(step)
40
+ else
41
+ ActiveRecord::Base.connection.migration_context.rollback(step)
42
+ end
31
43
  end
32
44
  end
33
45
  end
@@ -4,7 +4,9 @@ module Apartment
4
4
  module TaskHelper
5
5
  def self.each_tenant(&block)
6
6
  Parallel.each(tenants_without_default, in_threads: Apartment.parallel_migration_threads) do |tenant|
7
- block.call(tenant)
7
+ Rails.application.executor.wrap do
8
+ block.call(tenant)
9
+ end
8
10
  end
9
11
  end
10
12
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Apartment
4
- VERSION = '3.1.0'
4
+ VERSION = '3.2.0'
5
5
  end
data/lib/apartment.rb CHANGED
@@ -5,19 +5,25 @@ require 'active_support/core_ext/object/blank'
5
5
  require 'forwardable'
6
6
  require 'active_record'
7
7
  require 'apartment/tenant'
8
+ require 'apartment/deprecation'
8
9
 
9
10
  require_relative 'apartment/log_subscriber'
10
11
  require_relative 'apartment/active_record/connection_handling'
11
12
  require_relative 'apartment/active_record/schema_migration'
12
13
  require_relative 'apartment/active_record/internal_metadata'
13
14
 
15
+ if ActiveRecord.version.release >= Gem::Version.new('7.1')
16
+ require_relative 'apartment/active_record/postgres/schema_dumper'
17
+ end
18
+
14
19
  # Apartment main definitions
15
20
  module Apartment
16
21
  class << self
17
22
  extend Forwardable
18
23
 
19
24
  ACCESSOR_METHODS = %i[use_schemas use_sql seed_after_create prepend_environment default_tenant
20
- append_environment with_multi_server_setup tenant_presence_check active_record_log].freeze
25
+ append_environment with_multi_server_setup tenant_presence_check
26
+ active_record_log pg_exclude_clone_tables].freeze
21
27
 
22
28
  WRITER_METHODS = %i[tenant_names database_schema_file excluded_models
23
29
  persistent_schemas connection_class
@@ -47,7 +53,7 @@ module Apartment
47
53
  end
48
54
 
49
55
  def tld_length=(_)
50
- Apartment::Deprecation.warn('`config.tld_length` have no effect because it was removed in https://github.com/influitive/apartment/pull/309')
56
+ Apartment::DEPRECATOR.warn('`config.tld_length` have no effect because it was removed in https://github.com/influitive/apartment/pull/309')
51
57
  end
52
58
 
53
59
  def db_config_for(tenant)
@@ -7,10 +7,10 @@ Gem::Specification.new do |s|
7
7
  s.name = 'ros-apartment'
8
8
  s.version = Apartment::VERSION
9
9
 
10
- s.authors = ['Ryan Brunner', 'Brad Robertson', 'Rui Baltazar']
10
+ s.authors = ['Ryan Brunner', 'Brad Robertson', 'Rui Baltazar', 'Mauricio Novelo']
11
11
  s.summary = 'A Ruby gem for managing database multitenancy. Apartment Gem drop in replacement'
12
12
  s.description = 'Apartment allows Rack applications to deal with database multitenancy through ActiveRecord'
13
- s.email = ['ryan@influitive.com', 'brad@influitive.com', 'rui.p.baltazar@gmail.com']
13
+ s.email = ['ryan@influitive.com', 'brad@influitive.com', 'rui.p.baltazar@gmail.com', 'mauricio@campusesp.com']
14
14
  # Specify which files should be added to the gem when it is released.
15
15
  # The `git ls-files -z` loads the files in the RubyGem that have been
16
16
  # added into git.
@@ -21,45 +21,20 @@ Gem::Specification.new do |s|
21
21
  end
22
22
  end
23
23
  s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
24
- s.test_files = s.files.grep(%r{^(test|spec|features)/})
25
24
  s.require_paths = ['lib']
26
25
 
27
26
  s.homepage = 'https://github.com/rails-on-services/apartment'
28
27
  s.licenses = ['MIT']
29
28
  s.metadata = {
30
- 'github_repo' => 'ssh://github.com/rails-on-services/apartment'
29
+ 'github_repo' => 'ssh://github.com/rails-on-services/apartment',
30
+ 'rubygems_mfa_required' => 'true',
31
31
  }
32
32
 
33
- s.required_ruby_version = '>= 3.0', '< 3.4'
33
+ s.required_ruby_version = '>= 3.1'
34
34
 
35
- s.add_dependency 'activerecord', '>= 6.1.0', '< 7.2'
36
- s.add_dependency 'parallel', '< 2.0'
37
- s.add_dependency 'public_suffix', '>= 2.0.5', '< 6.0'
38
- s.add_dependency 'rack', '>= 1.3.6', '< 4.0'
39
-
40
- s.add_development_dependency 'appraisal', '~> 2.2'
41
- s.add_development_dependency 'bundler', '>= 1.3', '< 3.0'
42
- s.add_development_dependency 'guard-rspec', '~> 4.2'
43
- s.add_development_dependency 'pry'
44
- s.add_development_dependency 'rake', '~> 13.0'
45
- s.add_development_dependency 'rspec', '~> 3.4'
46
- s.add_development_dependency 'rspec_junit_formatter'
47
- s.add_development_dependency 'rspec-rails', '~> 6.1'
48
- s.add_development_dependency 'rubocop', '~> 1.63'
49
- s.add_development_dependency 'rubocop-performance', '~> 1.21'
50
- s.add_development_dependency 'rubocop-rails', '~> 2.24'
51
- s.add_development_dependency 'rubocop-rspec', '~> 2.29'
52
-
53
- if defined?(JRUBY_VERSION)
54
- s.add_development_dependency 'activerecord-jdbc-adapter'
55
- s.add_development_dependency 'activerecord-jdbcmysql-adapter'
56
- s.add_development_dependency 'activerecord-jdbcpostgresql-adapter'
57
- s.add_development_dependency 'jdbc-mysql'
58
- s.add_development_dependency 'jdbc-postgres'
59
- else
60
- s.add_development_dependency 'mysql2', '~> 0.5'
61
- s.add_development_dependency 'pg', '~> 1.5'
62
- s.add_development_dependency 'sqlite3', '< 2.0'
63
- s.add_development_dependency 'trilogy', '< 3.0'
64
- end
35
+ s.add_dependency('activerecord', '>= 6.1.0', '< 8.1')
36
+ s.add_dependency('activesupport', '>= 6.1.0', '< 8.1')
37
+ s.add_dependency('parallel', '< 2.0')
38
+ s.add_dependency('public_suffix', '>= 2.0.5', '<= 6.0.1')
39
+ s.add_dependency('rack', '>= 1.3.6', '< 4.0')
65
40
  end