ros-apartment 3.0.4 → 3.2.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.
@@ -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
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'apartment/adapters/mysql2_adapter'
4
+
5
+ module Apartment
6
+ # Helper module to decide wether to use trilogy adapter or trilogy adapter with schemas
7
+ module Tenant
8
+ def self.trilogy_adapter(config)
9
+ if Apartment.use_schemas
10
+ Adapters::TrilogySchemaAdapter.new(config)
11
+ else
12
+ Adapters::TrilogyAdapter.new(config)
13
+ end
14
+ end
15
+ end
16
+
17
+ module Adapters
18
+ class TrilogyAdapter < Mysql2Adapter
19
+ protected
20
+
21
+ def rescue_from
22
+ Trilogy::Error
23
+ end
24
+ end
25
+
26
+ class TrilogySchemaAdapter < Mysql2SchemaAdapter
27
+ end
28
+ end
29
+ 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.0.4'
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,44 +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
- 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')
64
40
  end