ros-apartment 2.7.1 → 2.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/changelog.yml +41 -0
- data/.rubocop.yml +73 -4
- data/.rubocop_todo.yml +50 -13
- data/.travis.yml +1 -1
- data/CHANGELOG.md +917 -0
- data/Gemfile +2 -2
- data/Guardfile +0 -15
- data/HISTORY.md +93 -92
- data/Rakefile +4 -2
- data/gemfiles/rails_5_0.gemfile +1 -1
- data/gemfiles/rails_5_1.gemfile +1 -1
- data/gemfiles/rails_5_2.gemfile +1 -1
- data/gemfiles/rails_6_0.gemfile +1 -1
- data/gemfiles/rails_master.gemfile +1 -1
- data/lib/apartment.rb +5 -3
- data/lib/apartment/active_record/connection_handling.rb +3 -0
- data/lib/apartment/active_record/internal_metadata.rb +0 -2
- data/lib/apartment/active_record/log_subscriber.rb +6 -3
- data/lib/apartment/active_record/schema_migration.rb +0 -2
- data/lib/apartment/adapters/abstract_adapter.rb +3 -3
- data/lib/apartment/adapters/abstract_jdbc_adapter.rb +2 -1
- data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +2 -1
- data/lib/apartment/adapters/mysql2_adapter.rb +3 -0
- data/lib/apartment/adapters/postgresql_adapter.rb +13 -6
- data/lib/apartment/console.rb +2 -8
- data/lib/apartment/custom_console.rb +2 -2
- data/lib/apartment/railtie.rb +1 -1
- data/lib/apartment/tasks/task_helper.rb +0 -2
- data/lib/apartment/tenant.rb +3 -1
- data/lib/apartment/version.rb +1 -1
- data/lib/generators/apartment/install/templates/apartment.rb +2 -1
- metadata +8 -6
data/Rakefile
CHANGED
@@ -46,8 +46,10 @@ namespace :db do
|
|
46
46
|
apartment_db_file = 'spec/config/database.yml'
|
47
47
|
rails_db_file = 'spec/dummy/config/database.yml'
|
48
48
|
|
49
|
-
|
50
|
-
|
49
|
+
unless File.exist?(apartment_db_file)
|
50
|
+
FileUtils.copy(apartment_db_file + '.sample', apartment_db_file, verbose: true)
|
51
|
+
end
|
52
|
+
FileUtils.copy(rails_db_file + '.sample', rails_db_file, verbose: true) unless File.exist?(rails_db_file)
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
data/gemfiles/rails_5_0.gemfile
CHANGED
data/gemfiles/rails_5_1.gemfile
CHANGED
data/gemfiles/rails_5_2.gemfile
CHANGED
data/gemfiles/rails_6_0.gemfile
CHANGED
data/lib/apartment.rb
CHANGED
@@ -6,16 +6,18 @@ require 'forwardable'
|
|
6
6
|
require 'active_record'
|
7
7
|
require 'apartment/tenant'
|
8
8
|
|
9
|
-
# require_relative 'apartment/arel/visitors/postgresql'
|
10
|
-
|
11
9
|
require_relative 'apartment/active_record/log_subscriber'
|
12
|
-
|
10
|
+
|
11
|
+
if ActiveRecord.version.release >= Gem::Version.new('6.0')
|
12
|
+
require_relative 'apartment/active_record/connection_handling'
|
13
|
+
end
|
13
14
|
|
14
15
|
if ActiveRecord.version.release >= Gem::Version.new('6.1')
|
15
16
|
require_relative 'apartment/active_record/schema_migration'
|
16
17
|
require_relative 'apartment/active_record/internal_metadata'
|
17
18
|
end
|
18
19
|
|
20
|
+
# Apartment main definitions
|
19
21
|
module Apartment
|
20
22
|
class << self
|
21
23
|
extend Forwardable
|
@@ -1,6 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
+
# This is monkeypatching activerecord to ensure that whenever a new connection is established it
|
5
|
+
# switches to the same tenant as before the connection switching. This problem is more evident when
|
6
|
+
# using read replica in Rails 6
|
4
7
|
module ConnectionHandling
|
5
8
|
def connected_to_with_tenant(database: nil, role: nil, prevent_writes: false, &blk)
|
6
9
|
current_tenant = Apartment::Tenant.current
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# rubocop:disable Rails/ApplicationRecord
|
4
3
|
class InternalMetadata < ActiveRecord::Base # :nodoc:
|
5
4
|
class << self
|
6
5
|
def table_exists?
|
@@ -8,4 +7,3 @@ class InternalMetadata < ActiveRecord::Base # :nodoc:
|
|
8
7
|
end
|
9
8
|
end
|
10
9
|
end
|
11
|
-
# rubocop:enable Rails/ApplicationRecord
|
@@ -1,13 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
+
# Supports the logging configuration to prepend the database and schema in the ActiveRecord log
|
4
5
|
class LogSubscriber
|
5
6
|
def apartment_log
|
6
7
|
return unless Apartment.active_record_log
|
7
8
|
|
8
9
|
database = color("[#{Apartment.connection.current_database}] ", ActiveSupport::LogSubscriber::MAGENTA, true)
|
9
10
|
schema = nil
|
10
|
-
|
11
|
+
unless Apartment.connection.schema_search_path.nil?
|
12
|
+
schema = color("[#{Apartment.connection.schema_search_path.tr('"', '')}] ",
|
13
|
+
ActiveSupport::LogSubscriber::YELLOW, true)
|
14
|
+
end
|
11
15
|
"#{database}#{schema}"
|
12
16
|
end
|
13
17
|
|
@@ -15,8 +19,7 @@ module ActiveRecord
|
|
15
19
|
return unless (binds || []).empty?
|
16
20
|
|
17
21
|
casted_params = type_casted_binds(type_casted_binds)
|
18
|
-
|
19
|
-
binds
|
22
|
+
' ' + binds.zip(casted_params).map { |attr, value| render_bind(attr, value) }.inspect
|
20
23
|
end
|
21
24
|
|
22
25
|
def sql(event)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
|
-
# rubocop:disable Rails/ApplicationRecord
|
5
4
|
class SchemaMigration < ActiveRecord::Base # :nodoc:
|
6
5
|
class << self
|
7
6
|
def table_exists?
|
@@ -9,5 +8,4 @@ module ActiveRecord
|
|
9
8
|
end
|
10
9
|
end
|
11
10
|
end
|
12
|
-
# rubocop:enable Rails/ApplicationRecord
|
13
11
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Apartment
|
4
4
|
module Adapters
|
5
|
-
#
|
5
|
+
# Abstract adapter from which all the Apartment DB related adapters will inherit the base logic
|
6
6
|
class AbstractAdapter
|
7
7
|
include ActiveSupport::Callbacks
|
8
8
|
define_callbacks :create, :switch
|
@@ -240,7 +240,8 @@ module Apartment
|
|
240
240
|
def with_neutral_connection(tenant, &_block)
|
241
241
|
if Apartment.with_multi_server_setup
|
242
242
|
# neutral connection is necessary whenever you need to create/remove a database from a server.
|
243
|
-
# example: when you use postgresql, you need to connect to the default postgresql database before you create
|
243
|
+
# example: when you use postgresql, you need to connect to the default postgresql database before you create
|
244
|
+
# your own.
|
244
245
|
SeparateDbConnectionHandler.establish_connection(multi_tenantify(tenant, false))
|
245
246
|
yield(SeparateDbConnectionHandler.connection)
|
246
247
|
SeparateDbConnectionHandler.connection.close
|
@@ -269,5 +270,4 @@ module Apartment
|
|
269
270
|
end
|
270
271
|
end
|
271
272
|
end
|
272
|
-
# rubocop:enable Metrics/ClassLength
|
273
273
|
end
|
@@ -4,11 +4,12 @@ require 'apartment/adapters/abstract_adapter'
|
|
4
4
|
|
5
5
|
module Apartment
|
6
6
|
module Adapters
|
7
|
+
# JDBC Abstract adapter
|
7
8
|
class AbstractJDBCAdapter < AbstractAdapter
|
8
9
|
private
|
9
10
|
|
10
11
|
def multi_tenantify_with_tenant_db_name(config, tenant)
|
11
|
-
config[:url] = "#{config[:url].gsub(%r{(\S+)
|
12
|
+
config[:url] = "#{config[:url].gsub(%r{(\S+)/.+$}, '\1')}/#{environmentify(tenant)}"
|
12
13
|
end
|
13
14
|
|
14
15
|
def rescue_from
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'apartment/adapters/postgresql_adapter'
|
4
4
|
|
5
5
|
module Apartment
|
6
|
+
# JDBC helper to decide wether to use JDBC Postgresql Adapter or JDBC Postgresql Adapter with Schemas
|
6
7
|
module Tenant
|
7
8
|
def self.jdbc_postgresql_adapter(config)
|
8
9
|
if Apartment.use_schemas
|
@@ -19,7 +20,7 @@ module Apartment
|
|
19
20
|
private
|
20
21
|
|
21
22
|
def multi_tenantify_with_tenant_db_name(config, tenant)
|
22
|
-
config[:url] = "#{config[:url].gsub(%r{(\S+)
|
23
|
+
config[:url] = "#{config[:url].gsub(%r{(\S+)/.+$}, '\1')}/#{environmentify(tenant)}"
|
23
24
|
end
|
24
25
|
|
25
26
|
def create_tenant_command(conn, tenant)
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'apartment/adapters/abstract_adapter'
|
4
4
|
|
5
5
|
module Apartment
|
6
|
+
# Helper module to decide wether to use mysql2 adapter or mysql2 adapter with schemas
|
6
7
|
module Tenant
|
7
8
|
def self.mysql2_adapter(config)
|
8
9
|
if Apartment.use_schemas
|
@@ -14,6 +15,7 @@ module Apartment
|
|
14
15
|
end
|
15
16
|
|
16
17
|
module Adapters
|
18
|
+
# Mysql2 Adapter
|
17
19
|
class Mysql2Adapter < AbstractAdapter
|
18
20
|
def initialize(config)
|
19
21
|
super
|
@@ -28,6 +30,7 @@ module Apartment
|
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
33
|
+
# Mysql2 Schemas Adapter
|
31
34
|
class Mysql2SchemaAdapter < AbstractAdapter
|
32
35
|
def initialize(config)
|
33
36
|
super
|
@@ -121,12 +121,17 @@ module Apartment
|
|
121
121
|
# There is `reset_sequence_name`, but that method actually goes to the database
|
122
122
|
# to find out the new name. Therefore, we do this hack to only unset the name,
|
123
123
|
# and it will be dynamically found the next time it is needed
|
124
|
-
ActiveRecord::Base.descendants
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
124
|
+
descendants_to_unset = ActiveRecord::Base.descendants
|
125
|
+
.select { |c| c.instance_variable_defined?(:@sequence_name) }
|
126
|
+
.reject do |c|
|
127
|
+
c.instance_variable_defined?(:@explicit_sequence_name) &&
|
128
|
+
c.instance_variable_get(:@explicit_sequence_name)
|
129
|
+
end
|
130
|
+
descendants_to_unset.each do |c|
|
131
|
+
# NOTE: due to this https://github.com/rails-on-services/apartment/issues/81
|
132
|
+
# unreproduceable error we're checking before trying to remove it
|
133
|
+
c.remove_instance_variable :@sequence_name if c.instance_variable_defined?(:@sequence_name)
|
134
|
+
end
|
130
135
|
end
|
131
136
|
end
|
132
137
|
|
@@ -195,9 +200,11 @@ module Apartment
|
|
195
200
|
#
|
196
201
|
# @return {String} raw SQL contaning inserts with data from schema_migrations
|
197
202
|
#
|
203
|
+
# rubocop:disable Layout/LineLength
|
198
204
|
def pg_dump_schema_migrations_data
|
199
205
|
with_pg_env { `pg_dump -a --inserts -t #{default_tenant}.schema_migrations -t #{default_tenant}.ar_internal_metadata #{dbname}` }
|
200
206
|
end
|
207
|
+
# rubocop:enable Layout/LineLength
|
201
208
|
|
202
209
|
# Temporary set Postgresql related environment variables if there are in @config
|
203
210
|
#
|
data/lib/apartment/console.rb
CHANGED
@@ -5,9 +5,7 @@
|
|
5
5
|
|
6
6
|
# reloads the environment
|
7
7
|
def reload!(print = true)
|
8
|
-
# rubocop:disable Rails/Output
|
9
8
|
puts 'Reloading...' if print
|
10
|
-
# rubocop:enable Rails/Output
|
11
9
|
|
12
10
|
# This triggers the to_prepare callbacks
|
13
11
|
ActionDispatch::Callbacks.new(proc {}).call({})
|
@@ -18,15 +16,13 @@ end
|
|
18
16
|
|
19
17
|
def st(schema_name = nil)
|
20
18
|
if schema_name.nil?
|
21
|
-
# rubocop:disable Rails/Output
|
22
19
|
tenant_list.each { |t| puts t }
|
23
|
-
|
20
|
+
|
24
21
|
elsif tenant_list.include? schema_name
|
25
22
|
Apartment::Tenant.switch!(schema_name)
|
26
23
|
else
|
27
|
-
# rubocop:disable Rails/Output
|
28
24
|
puts "Tenant #{schema_name} is not part of the tenant list"
|
29
|
-
|
25
|
+
|
30
26
|
end
|
31
27
|
end
|
32
28
|
|
@@ -37,8 +33,6 @@ def tenant_list
|
|
37
33
|
end
|
38
34
|
|
39
35
|
def tenant_info_msg
|
40
|
-
# rubocop:disable Rails/Output
|
41
36
|
puts "Available Tenants: #{tenant_list}\n"
|
42
37
|
puts "Use `st 'tenant'` to switch tenants & `tenant_list` to see list\n"
|
43
|
-
# rubocop:enable Rails/Output
|
44
38
|
end
|
@@ -7,9 +7,9 @@ module Apartment
|
|
7
7
|
begin
|
8
8
|
require 'pry-rails'
|
9
9
|
rescue LoadError
|
10
|
-
# rubocop:disable
|
10
|
+
# rubocop:disable Layout/LineLength
|
11
11
|
puts '[Failed to load pry-rails] If you want to use Apartment custom prompt you need to add pry-rails to your gemfile'
|
12
|
-
# rubocop:enable
|
12
|
+
# rubocop:enable Layout/LineLength
|
13
13
|
end
|
14
14
|
|
15
15
|
desc = "Includes the current Rails environment and project folder name.\n" \
|
data/lib/apartment/railtie.rb
CHANGED
@@ -19,7 +19,6 @@ module Apartment
|
|
19
19
|
def self.warn_if_tenants_empty
|
20
20
|
return unless tenants.empty? && ENV['IGNORE_EMPTY_TENANTS'] != 'true'
|
21
21
|
|
22
|
-
# rubocop:disable Rails/Output
|
23
22
|
puts <<-WARNING
|
24
23
|
[WARNING] - The list of tenants to migrate appears to be empty. This could mean a few things:
|
25
24
|
|
@@ -29,7 +28,6 @@ module Apartment
|
|
29
28
|
|
30
29
|
Note that your tenants currently haven't been migrated. You'll need to run `db:migrate` to rectify this.
|
31
30
|
WARNING
|
32
|
-
# rubocop:enable Rails/Output
|
33
31
|
end
|
34
32
|
end
|
35
33
|
end
|
data/lib/apartment/tenant.rb
CHANGED
@@ -51,7 +51,9 @@ module Apartment
|
|
51
51
|
raise "The adapter `#{adapter_method}` is not yet supported"
|
52
52
|
end
|
53
53
|
|
54
|
-
|
54
|
+
unless respond_to?(adapter_method)
|
55
|
+
raise AdapterNotFound, "database configuration specifies nonexistent #{config[:adapter]} adapter"
|
56
|
+
end
|
55
57
|
|
56
58
|
send(adapter_method, config)
|
57
59
|
end
|
data/lib/apartment/version.rb
CHANGED
@@ -23,7 +23,8 @@ Apartment.configure do |config|
|
|
23
23
|
# You can make this dynamic by providing a Proc object to be called on migrations.
|
24
24
|
# This object should yield either:
|
25
25
|
# - an array of strings representing each Tenant name.
|
26
|
-
# - a hash which keys are tenant names, and values custom db config
|
26
|
+
# - a hash which keys are tenant names, and values custom db config
|
27
|
+
# (must contain all key/values required in database.yml)
|
27
28
|
#
|
28
29
|
# config.tenant_names = lambda{ Customer.pluck(:tenant_name) }
|
29
30
|
# config.tenant_names = ['tenant1', 'tenant2']
|
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ros-apartment
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.7.
|
4
|
+
version: 2.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Brunner
|
8
8
|
- Brad Robertson
|
9
9
|
- Rui Baltazar
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-
|
13
|
+
date: 2020-07-17 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -229,6 +229,7 @@ extensions: []
|
|
229
229
|
extra_rdoc_files: []
|
230
230
|
files:
|
231
231
|
- ".github/ISSUE_TEMPLATE.md"
|
232
|
+
- ".github/workflows/changelog.yml"
|
232
233
|
- ".gitignore"
|
233
234
|
- ".pryrc"
|
234
235
|
- ".rspec"
|
@@ -237,6 +238,7 @@ files:
|
|
237
238
|
- ".story_branch.yml"
|
238
239
|
- ".travis.yml"
|
239
240
|
- Appraisals
|
241
|
+
- CHANGELOG.md
|
240
242
|
- Gemfile
|
241
243
|
- Guardfile
|
242
244
|
- HISTORY.md
|
@@ -289,7 +291,7 @@ homepage: https://github.com/rails-on-services/apartment
|
|
289
291
|
licenses:
|
290
292
|
- MIT
|
291
293
|
metadata: {}
|
292
|
-
post_install_message:
|
294
|
+
post_install_message:
|
293
295
|
rdoc_options: []
|
294
296
|
require_paths:
|
295
297
|
- lib
|
@@ -304,8 +306,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
304
306
|
- !ruby/object:Gem::Version
|
305
307
|
version: '0'
|
306
308
|
requirements: []
|
307
|
-
rubygems_version: 3.
|
308
|
-
signing_key:
|
309
|
+
rubygems_version: 3.1.4
|
310
|
+
signing_key:
|
309
311
|
specification_version: 4
|
310
312
|
summary: A Ruby gem for managing database multitenancy. Apartment Gem drop in replacement
|
311
313
|
test_files: []
|