ros-apartment 2.6.0 → 2.8.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/changelog.yml +63 -0
  3. data/.rubocop.yml +74 -4
  4. data/.rubocop_todo.yml +50 -13
  5. data/.story_branch.yml +1 -0
  6. data/.travis.yml +5 -0
  7. data/CHANGELOG.md +949 -0
  8. data/Gemfile +1 -1
  9. data/Guardfile +0 -15
  10. data/HISTORY.md +159 -68
  11. data/README.md +13 -3
  12. data/Rakefile +4 -2
  13. data/TODO.md +0 -1
  14. data/gemfiles/rails_5_0.gemfile +1 -1
  15. data/gemfiles/rails_5_1.gemfile +1 -1
  16. data/gemfiles/rails_5_2.gemfile +1 -1
  17. data/gemfiles/rails_6_0.gemfile +1 -1
  18. data/gemfiles/rails_master.gemfile +1 -1
  19. data/lib/apartment.rb +13 -12
  20. data/lib/apartment/active_record/connection_handling.rb +3 -0
  21. data/lib/apartment/active_record/internal_metadata.rb +0 -2
  22. data/lib/apartment/active_record/schema_migration.rb +0 -2
  23. data/lib/apartment/adapters/abstract_adapter.rb +9 -4
  24. data/lib/apartment/adapters/abstract_jdbc_adapter.rb +2 -1
  25. data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +2 -1
  26. data/lib/apartment/adapters/mysql2_adapter.rb +5 -0
  27. data/lib/apartment/adapters/postgresql_adapter.rb +48 -1
  28. data/lib/apartment/console.rb +2 -8
  29. data/lib/apartment/custom_console.rb +4 -2
  30. data/lib/apartment/log_subscriber.rb +27 -0
  31. data/lib/apartment/railtie.rb +15 -10
  32. data/lib/apartment/tasks/task_helper.rb +40 -0
  33. data/lib/apartment/tenant.rb +4 -8
  34. data/lib/apartment/version.rb +1 -1
  35. data/lib/generators/apartment/install/templates/apartment.rb +7 -1
  36. data/lib/tasks/apartment.rake +18 -42
  37. data/{apartment.gemspec → ros-apartment.gemspec} +2 -4
  38. metadata +15 -12
  39. data/.github/workflows/.rubocop-linter.yml +0 -22
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'console'
4
+
3
5
  module Apartment
4
6
  module CustomConsole
5
7
  begin
6
8
  require 'pry-rails'
7
9
  rescue LoadError
8
- # rubocop:disable Rails/Output
10
+ # rubocop:disable Layout/LineLength
9
11
  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
12
+ # rubocop:enable Layout/LineLength
11
13
  end
12
14
 
13
15
  desc = "Includes the current Rails environment and project folder name.\n" \
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apartment
4
+ class LogSubscriber < ActiveRecord::LogSubscriber
5
+ def sql(event)
6
+ super(event)
7
+ end
8
+
9
+ private
10
+
11
+ def debug(progname = nil, &block)
12
+ progname = " #{apartment_log}#{progname}" unless progname.nil?
13
+
14
+ super(progname, &block)
15
+ end
16
+
17
+ def apartment_log
18
+ database = color("[#{Apartment.connection.current_database}] ", ActiveSupport::LogSubscriber::MAGENTA, true)
19
+ schema = nil
20
+ unless Apartment.connection.schema_search_path.nil?
21
+ schema = color("[#{Apartment.connection.schema_search_path.tr('"', '')}] ",
22
+ ActiveSupport::LogSubscriber::YELLOW, true)
23
+ end
24
+ "#{database}#{schema}"
25
+ end
26
+ end
27
+ end
@@ -6,6 +6,7 @@ require 'apartment/reloader'
6
6
 
7
7
  module Apartment
8
8
  class Railtie < Rails::Railtie
9
+
9
10
  #
10
11
  # Set up our default config options
11
12
  # Do this before the app initializers run so we don't override custom settings
@@ -19,6 +20,7 @@ module Apartment
19
20
  config.prepend_environment = false
20
21
  config.append_environment = false
21
22
  config.tenant_presence_check = true
23
+ config.active_record_log = false
22
24
  end
23
25
 
24
26
  ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a
@@ -31,17 +33,23 @@ module Apartment
31
33
  config.to_prepare do
32
34
  next if ARGV.any? { |arg| arg =~ /\Aassets:(?:precompile|clean)\z/ }
33
35
  next if ARGV.any? { |arg| arg == 'webpacker:compile' }
36
+ next if ENV["APARTMENT_DISABLE_INIT"]
34
37
 
35
38
  begin
36
39
  Apartment.connection_class.connection_pool.with_connection do
37
40
  Apartment::Tenant.init
38
41
  end
39
- rescue ::ActiveRecord::NoDatabaseError, PG::ConnectionBad
42
+ rescue ::ActiveRecord::NoDatabaseError
40
43
  # Since `db:create` and other tasks invoke this block from Rails 5.2.0,
41
44
  # we need to swallow the error to execute `db:create` properly.
42
- Rails.logger.warn do
43
- 'Failed to initialize Apartment because a database connection could not be established.'
44
- end
45
+ end
46
+ end
47
+
48
+ config.after_initialize do |app|
49
+ # NOTE: Load the custom log subscriber if enabled
50
+ if Apartment.active_record_log
51
+ ActiveSupport::Notifications.unsubscribe 'sql.active_record'
52
+ Apartment::LogSubscriber.attach_to :active_record
45
53
  end
46
54
  end
47
55
 
@@ -54,10 +62,8 @@ module Apartment
54
62
  end
55
63
 
56
64
  #
57
- # The following initializers are a workaround to the fact that I can't
58
- # properly hook into the rails reloader
59
- # Note this is technically valid for any environment where cache_classes
60
- # is false, for us, it's just development
65
+ # The following initializers are a workaround to the fact that I can't properly hook into the rails reloader
66
+ # Note this is technically valid for any environment where cache_classes is false, for us, it's just development
61
67
  #
62
68
  if Rails.env.development?
63
69
 
@@ -66,8 +72,7 @@ module Apartment
66
72
  app.config.middleware.use Apartment::Reloader
67
73
  end
68
74
 
69
- # Overrides reload! to also call Apartment::Tenant.init as well so that the
70
- # reloaded classes have the proper table_names
75
+ # Overrides reload! to also call Apartment::Tenant.init as well so that the reloaded classes have the proper table_names
71
76
  console do
72
77
  require 'apartment/console'
73
78
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apartment
4
+ module TaskHelper
5
+ def self.each_tenant(&block)
6
+ Parallel.each(tenants_without_default, in_threads: Apartment.parallel_migration_threads) do |tenant|
7
+ block.call(tenant)
8
+ end
9
+ end
10
+
11
+ def self.tenants_without_default
12
+ tenants - [Apartment.default_tenant]
13
+ end
14
+
15
+ def self.tenants
16
+ ENV['DB'] ? ENV['DB'].split(',').map(&:strip) : Apartment.tenant_names || []
17
+ end
18
+
19
+ def self.warn_if_tenants_empty
20
+ return unless tenants.empty? && ENV['IGNORE_EMPTY_TENANTS'] != 'true'
21
+
22
+ puts <<-WARNING
23
+ [WARNING] - The list of tenants to migrate appears to be empty. This could mean a few things:
24
+
25
+ 1. You may not have created any, in which case you can ignore this message
26
+ 2. You've run `apartment:migrate` directly without loading the Rails environment
27
+ * `apartment:migrate` is now deprecated. Tenants will automatically be migrated with `db:migrate`
28
+
29
+ Note that your tenants currently haven't been migrated. You'll need to run `db:migrate` to rectify this.
30
+ WARNING
31
+ end
32
+
33
+ def self.create_tenant(tenant_name)
34
+ puts("Creating #{tenant_name} tenant")
35
+ Apartment::Tenant.create(tenant_name)
36
+ rescue Apartment::TenantExists => e
37
+ puts "Tried to create already existing tenant: #{e}"
38
+ end
39
+ end
40
+ end
@@ -10,17 +10,11 @@ module Apartment
10
10
  extend Forwardable
11
11
 
12
12
  def_delegators :adapter, :create, :drop, :switch, :switch!, :current, :each,
13
- :reset, :set_callback, :seed, :current_tenant,
13
+ :reset, :init, :set_callback, :seed, :current_tenant,
14
14
  :default_tenant, :environmentify
15
15
 
16
16
  attr_writer :config
17
17
 
18
- # Initialize Apartment config options such as excluded_models
19
- #
20
- def init
21
- adapter.process_excluded_models
22
- end
23
-
24
18
  # Fetch the proper multi-tenant adapter based on Rails config
25
19
  #
26
20
  # @return {subclass of Apartment::AbstractAdapter}
@@ -43,7 +37,9 @@ module Apartment
43
37
  raise "The adapter `#{adapter_method}` is not yet supported"
44
38
  end
45
39
 
46
- raise AdapterNotFound, "database configuration specifies nonexistent #{config[:adapter]} adapter" unless respond_to?(adapter_method)
40
+ unless respond_to?(adapter_method)
41
+ raise AdapterNotFound, "database configuration specifies nonexistent #{config[:adapter]} adapter"
42
+ end
47
43
 
48
44
  send(adapter_method, config)
49
45
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Apartment
4
- VERSION = '2.6.0'
4
+ VERSION = '2.8.0'
5
5
  end
@@ -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 (must contain all key/values required in database.yml)
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']
@@ -96,6 +97,11 @@ Apartment.configure do |config|
96
97
  # the new tenant
97
98
  #
98
99
  # config.pg_excluded_names = ["uuid_generate_v4"]
100
+
101
+ # Specifies whether the database and schema (when using PostgreSQL schemas) will prepend in ActiveRecord log.
102
+ # Uncomment the line below if you want to enable this behavior.
103
+ #
104
+ # config.active_record_log = true
99
105
  end
100
106
 
101
107
  # Setup a custom Tenant switching middleware. The Proc should return the name of the Tenant that
@@ -1,24 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'apartment/migrator'
4
+ require 'apartment/tasks/task_helper'
4
5
  require 'parallel'
5
6
 
6
7
  apartment_namespace = namespace :apartment do
7
8
  desc 'Create all tenants'
8
9
  task :create do
9
- tenants.each do |tenant|
10
- begin
11
- puts("Creating #{tenant} tenant")
12
- Apartment::Tenant.create(tenant)
13
- rescue Apartment::TenantExists => e
14
- puts e.message
15
- end
10
+ Apartment::TaskHelper.warn_if_tenants_empty
11
+
12
+ Apartment::TaskHelper.tenants.each do |tenant|
13
+ Apartment::TaskHelper.create_tenant(tenant)
16
14
  end
17
15
  end
18
16
 
19
17
  desc 'Drop all tenants'
20
18
  task :drop do
21
- tenants.each do |tenant|
19
+ Apartment::TaskHelper.tenants.each do |tenant|
22
20
  begin
23
21
  puts("Dropping #{tenant} tenant")
24
22
  Apartment::Tenant.drop(tenant)
@@ -30,9 +28,10 @@ apartment_namespace = namespace :apartment do
30
28
 
31
29
  desc 'Migrate all tenants'
32
30
  task :migrate do
33
- warn_if_tenants_empty
34
- each_tenant do |tenant|
31
+ Apartment::TaskHelper.warn_if_tenants_empty
32
+ Apartment::TaskHelper.each_tenant do |tenant|
35
33
  begin
34
+ Apartment::TaskHelper.create_tenant(tenant)
36
35
  puts("Migrating #{tenant} tenant")
37
36
  Apartment::Migrator.migrate tenant
38
37
  rescue Apartment::TenantNotFound => e
@@ -43,10 +42,11 @@ apartment_namespace = namespace :apartment do
43
42
 
44
43
  desc 'Seed all tenants'
45
44
  task :seed do
46
- warn_if_tenants_empty
45
+ Apartment::TaskHelper.warn_if_tenants_empty
47
46
 
48
- each_tenant do |tenant|
47
+ Apartment::TaskHelper.each_tenant do |tenant|
49
48
  begin
49
+ Apartment::TaskHelper.create_tenant(tenant)
50
50
  puts("Seeding #{tenant} tenant")
51
51
  Apartment::Tenant.switch(tenant) do
52
52
  Apartment::Tenant.seed
@@ -59,11 +59,11 @@ apartment_namespace = namespace :apartment do
59
59
 
60
60
  desc 'Rolls the migration back to the previous version (specify steps w/ STEP=n) across all tenants.'
61
61
  task :rollback do
62
- warn_if_tenants_empty
62
+ Apartment::TaskHelper.warn_if_tenants_empty
63
63
 
64
64
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
65
65
 
66
- each_tenant do |tenant|
66
+ Apartment::TaskHelper.each_tenant do |tenant|
67
67
  begin
68
68
  puts("Rolling back #{tenant} tenant")
69
69
  Apartment::Migrator.rollback tenant, step
@@ -76,12 +76,12 @@ apartment_namespace = namespace :apartment do
76
76
  namespace :migrate do
77
77
  desc 'Runs the "up" for a given migration VERSION across all tenants.'
78
78
  task :up do
79
- warn_if_tenants_empty
79
+ Apartment::TaskHelper.warn_if_tenants_empty
80
80
 
81
81
  version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
82
82
  raise 'VERSION is required' unless version
83
83
 
84
- each_tenant do |tenant|
84
+ Apartment::TaskHelper.each_tenant do |tenant|
85
85
  begin
86
86
  puts("Migrating #{tenant} tenant up")
87
87
  Apartment::Migrator.run :up, tenant, version
@@ -93,12 +93,12 @@ apartment_namespace = namespace :apartment do
93
93
 
94
94
  desc 'Runs the "down" for a given migration VERSION across all tenants.'
95
95
  task :down do
96
- warn_if_tenants_empty
96
+ Apartment::TaskHelper.warn_if_tenants_empty
97
97
 
98
98
  version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
99
99
  raise 'VERSION is required' unless version
100
100
 
101
- each_tenant do |tenant|
101
+ Apartment::TaskHelper.each_tenant do |tenant|
102
102
  begin
103
103
  puts("Migrating #{tenant} tenant down")
104
104
  Apartment::Migrator.run :down, tenant, version
@@ -119,28 +119,4 @@ apartment_namespace = namespace :apartment do
119
119
  end
120
120
  end
121
121
  end
122
-
123
- def each_tenant(&block)
124
- Parallel.each(tenants, in_threads: Apartment.parallel_migration_threads) do |tenant|
125
- block.call(tenant)
126
- end
127
- end
128
-
129
- def tenants
130
- ENV['DB'] ? ENV['DB'].split(',').map(&:strip) : Apartment.tenant_names || []
131
- end
132
-
133
- def warn_if_tenants_empty
134
- return unless tenants.empty? && ENV['IGNORE_EMPTY_TENANTS'] != 'true'
135
-
136
- puts <<-WARNING
137
- [WARNING] - The list of tenants to migrate appears to be empty. This could mean a few things:
138
-
139
- 1. You may not have created any, in which case you can ignore this message
140
- 2. You've run `apartment:migrate` directly without loading the Rails environment
141
- * `apartment:migrate` is now deprecated. Tenants will automatically be migrated with `db:migrate`
142
-
143
- Note that your tenants currently haven't been migrated. You'll need to run `db:migrate` to rectify this.
144
- WARNING
145
- end
146
122
  end
@@ -27,8 +27,7 @@ Gem::Specification.new do |s|
27
27
  s.homepage = 'https://github.com/rails-on-services/apartment'
28
28
  s.licenses = ['MIT']
29
29
 
30
- # must be >= 3.1.2 due to bug in prepared_statements
31
- s.add_dependency 'activerecord', '>= 5.0.0', '< 6.1'
30
+ s.add_dependency 'activerecord', '>= 5.0.0', '< 6.2'
32
31
  s.add_dependency 'parallel', '< 2.0'
33
32
  s.add_dependency 'public_suffix', '>= 2.0.5', '< 5.0'
34
33
  s.add_dependency 'rack', '>= 1.3.6', '< 3.0'
@@ -36,7 +35,7 @@ Gem::Specification.new do |s|
36
35
  s.add_development_dependency 'appraisal', '~> 2.2'
37
36
  s.add_development_dependency 'bundler', '>= 1.3', '< 3.0'
38
37
  s.add_development_dependency 'capybara', '~> 2.0'
39
- s.add_development_dependency 'rake', '~> 0.9'
38
+ s.add_development_dependency 'rake', '~> 13.0'
40
39
  s.add_development_dependency 'rspec', '~> 3.4'
41
40
  s.add_development_dependency 'rspec-rails', '~> 3.4'
42
41
 
@@ -46,7 +45,6 @@ Gem::Specification.new do |s|
46
45
  s.add_development_dependency 'activerecord-jdbcpostgresql-adapter'
47
46
  s.add_development_dependency 'jdbc-mysql'
48
47
  s.add_development_dependency 'jdbc-postgres'
49
- s.add_development_dependency 'jruby-openssl'
50
48
  else
51
49
  s.add_development_dependency 'mysql2', '~> 0.5'
52
50
  s.add_development_dependency 'pg', '~> 1.2'
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.6.0
4
+ version: 2.8.0
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-05-14 00:00:00.000000000 Z
13
+ date: 2020-12-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 5.0.0
22
22
  - - "<"
23
23
  - !ruby/object:Gem::Version
24
- version: '6.1'
24
+ version: '6.2'
25
25
  type: :runtime
26
26
  prerelease: false
27
27
  version_requirements: !ruby/object:Gem::Requirement
@@ -31,7 +31,7 @@ dependencies:
31
31
  version: 5.0.0
32
32
  - - "<"
33
33
  - !ruby/object:Gem::Version
34
- version: '6.1'
34
+ version: '6.2'
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: parallel
37
37
  requirement: !ruby/object:Gem::Requirement
@@ -140,14 +140,14 @@ dependencies:
140
140
  requirements:
141
141
  - - "~>"
142
142
  - !ruby/object:Gem::Version
143
- version: '0.9'
143
+ version: '13.0'
144
144
  type: :development
145
145
  prerelease: false
146
146
  version_requirements: !ruby/object:Gem::Requirement
147
147
  requirements:
148
148
  - - "~>"
149
149
  - !ruby/object:Gem::Version
150
- version: '0.9'
150
+ version: '13.0'
151
151
  - !ruby/object:Gem::Dependency
152
152
  name: rspec
153
153
  requirement: !ruby/object:Gem::Requirement
@@ -229,7 +229,7 @@ extensions: []
229
229
  extra_rdoc_files: []
230
230
  files:
231
231
  - ".github/ISSUE_TEMPLATE.md"
232
- - ".github/workflows/.rubocop-linter.yml"
232
+ - ".github/workflows/changelog.yml"
233
233
  - ".gitignore"
234
234
  - ".pryrc"
235
235
  - ".rspec"
@@ -238,13 +238,13 @@ files:
238
238
  - ".story_branch.yml"
239
239
  - ".travis.yml"
240
240
  - Appraisals
241
+ - CHANGELOG.md
241
242
  - Gemfile
242
243
  - Guardfile
243
244
  - HISTORY.md
244
245
  - README.md
245
246
  - Rakefile
246
247
  - TODO.md
247
- - apartment.gemspec
248
248
  - docker-compose.yml
249
249
  - gemfiles/rails_4_2.gemfile
250
250
  - gemfiles/rails_5_0.gemfile
@@ -273,22 +273,25 @@ files:
273
273
  - lib/apartment/elevators/host.rb
274
274
  - lib/apartment/elevators/host_hash.rb
275
275
  - lib/apartment/elevators/subdomain.rb
276
+ - lib/apartment/log_subscriber.rb
276
277
  - lib/apartment/migrator.rb
277
278
  - lib/apartment/model.rb
278
279
  - lib/apartment/railtie.rb
279
280
  - lib/apartment/reloader.rb
280
281
  - lib/apartment/tasks/enhancements.rb
282
+ - lib/apartment/tasks/task_helper.rb
281
283
  - lib/apartment/tenant.rb
282
284
  - lib/apartment/version.rb
283
285
  - lib/generators/apartment/install/USAGE
284
286
  - lib/generators/apartment/install/install_generator.rb
285
287
  - lib/generators/apartment/install/templates/apartment.rb
286
288
  - lib/tasks/apartment.rake
289
+ - ros-apartment.gemspec
287
290
  homepage: https://github.com/rails-on-services/apartment
288
291
  licenses:
289
292
  - MIT
290
293
  metadata: {}
291
- post_install_message:
294
+ post_install_message:
292
295
  rdoc_options: []
293
296
  require_paths:
294
297
  - lib
@@ -303,8 +306,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
303
306
  - !ruby/object:Gem::Version
304
307
  version: '0'
305
308
  requirements: []
306
- rubygems_version: 3.0.3
307
- signing_key:
309
+ rubygems_version: 3.1.4
310
+ signing_key:
308
311
  specification_version: 4
309
312
  summary: A Ruby gem for managing database multitenancy. Apartment Gem drop in replacement
310
313
  test_files: []