ros-apartment 2.4.0 → 2.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +5 -0
  3. data/.rubocop_todo.yml +1 -1
  4. data/.story_branch.yml +1 -0
  5. data/.travis.yml +13 -30
  6. data/Appraisals +4 -17
  7. data/Gemfile +2 -2
  8. data/Guardfile +3 -1
  9. data/HISTORY.md +90 -0
  10. data/README.md +31 -16
  11. data/Rakefile +34 -22
  12. data/TODO.md +0 -1
  13. data/gemfiles/rails_5_0.gemfile +10 -11
  14. data/gemfiles/rails_5_1.gemfile +10 -11
  15. data/gemfiles/rails_5_2.gemfile +9 -10
  16. data/gemfiles/rails_6_0.gemfile +10 -11
  17. data/gemfiles/rails_master.gemfile +10 -11
  18. data/lib/apartment.rb +31 -13
  19. data/lib/apartment/active_record/connection_handling.rb +17 -0
  20. data/lib/apartment/active_record/internal_metadata.rb +11 -0
  21. data/lib/apartment/active_record/log_subscriber.rb +41 -0
  22. data/lib/apartment/active_record/schema_migration.rb +13 -0
  23. data/lib/apartment/adapters/abstract_adapter.rb +17 -13
  24. data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +9 -4
  25. data/lib/apartment/adapters/mysql2_adapter.rb +2 -0
  26. data/lib/apartment/adapters/postgresql_adapter.rb +33 -4
  27. data/lib/apartment/adapters/sqlite3_adapter.rb +2 -0
  28. data/lib/apartment/console.rb +7 -0
  29. data/lib/apartment/custom_console.rb +23 -7
  30. data/lib/apartment/model.rb +27 -0
  31. data/lib/apartment/railtie.rb +19 -15
  32. data/lib/apartment/tasks/task_helper.rb +35 -0
  33. data/lib/apartment/tenant.rb +16 -5
  34. data/lib/apartment/version.rb +1 -1
  35. data/lib/generators/apartment/install/templates/apartment.rb +5 -0
  36. data/lib/tasks/apartment.rake +16 -37
  37. data/{apartment.gemspec → ros-apartment.gemspec} +12 -6
  38. metadata +16 -213
  39. data/.github/workflows/.rubocop-linter.yml +0 -22
  40. data/spec/adapters/jdbc_mysql_adapter_spec.rb +0 -20
  41. data/spec/adapters/jdbc_postgresql_adapter_spec.rb +0 -39
  42. data/spec/adapters/mysql2_adapter_spec.rb +0 -61
  43. data/spec/adapters/postgresql_adapter_spec.rb +0 -63
  44. data/spec/adapters/sqlite3_adapter_spec.rb +0 -101
  45. data/spec/apartment_spec.rb +0 -13
  46. data/spec/config/database.yml.sample +0 -49
  47. data/spec/dummy/Rakefile +0 -7
  48. data/spec/dummy/app/controllers/application_controller.rb +0 -7
  49. data/spec/dummy/app/helpers/application_helper.rb +0 -4
  50. data/spec/dummy/app/models/application_record.rb +0 -6
  51. data/spec/dummy/app/models/company.rb +0 -5
  52. data/spec/dummy/app/models/user.rb +0 -5
  53. data/spec/dummy/app/views/application/index.html.erb +0 -1
  54. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  55. data/spec/dummy/config.ru +0 -6
  56. data/spec/dummy/config/application.rb +0 -51
  57. data/spec/dummy/config/boot.rb +0 -13
  58. data/spec/dummy/config/database.yml.sample +0 -44
  59. data/spec/dummy/config/environment.rb +0 -7
  60. data/spec/dummy/config/environments/development.rb +0 -29
  61. data/spec/dummy/config/environments/production.rb +0 -53
  62. data/spec/dummy/config/environments/test.rb +0 -36
  63. data/spec/dummy/config/initializers/apartment.rb +0 -6
  64. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
  65. data/spec/dummy/config/initializers/inflections.rb +0 -11
  66. data/spec/dummy/config/initializers/mime_types.rb +0 -6
  67. data/spec/dummy/config/initializers/secret_token.rb +0 -9
  68. data/spec/dummy/config/initializers/session_store.rb +0 -10
  69. data/spec/dummy/config/locales/en.yml +0 -5
  70. data/spec/dummy/config/routes.rb +0 -5
  71. data/spec/dummy/db/migrate/20110613152810_create_dummy_models.rb +0 -39
  72. data/spec/dummy/db/migrate/20111202022214_create_table_books.rb +0 -14
  73. data/spec/dummy/db/migrate/20180415260934_create_public_tokens.rb +0 -13
  74. data/spec/dummy/db/schema.rb +0 -55
  75. data/spec/dummy/db/seeds.rb +0 -5
  76. data/spec/dummy/db/seeds/import.rb +0 -7
  77. data/spec/dummy/public/404.html +0 -26
  78. data/spec/dummy/public/422.html +0 -26
  79. data/spec/dummy/public/500.html +0 -26
  80. data/spec/dummy/public/favicon.ico +0 -0
  81. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  82. data/spec/dummy/script/rails +0 -8
  83. data/spec/dummy_engine/.gitignore +0 -8
  84. data/spec/dummy_engine/Gemfile +0 -15
  85. data/spec/dummy_engine/Rakefile +0 -34
  86. data/spec/dummy_engine/bin/rails +0 -12
  87. data/spec/dummy_engine/config/initializers/apartment.rb +0 -52
  88. data/spec/dummy_engine/dummy_engine.gemspec +0 -24
  89. data/spec/dummy_engine/lib/dummy_engine.rb +0 -6
  90. data/spec/dummy_engine/lib/dummy_engine/engine.rb +0 -6
  91. data/spec/dummy_engine/lib/dummy_engine/version.rb +0 -5
  92. data/spec/dummy_engine/test/dummy/Rakefile +0 -6
  93. data/spec/dummy_engine/test/dummy/config.ru +0 -6
  94. data/spec/dummy_engine/test/dummy/config/application.rb +0 -24
  95. data/spec/dummy_engine/test/dummy/config/boot.rb +0 -7
  96. data/spec/dummy_engine/test/dummy/config/database.yml +0 -25
  97. data/spec/dummy_engine/test/dummy/config/environment.rb +0 -7
  98. data/spec/dummy_engine/test/dummy/config/environments/development.rb +0 -39
  99. data/spec/dummy_engine/test/dummy/config/environments/production.rb +0 -80
  100. data/spec/dummy_engine/test/dummy/config/environments/test.rb +0 -41
  101. data/spec/dummy_engine/test/dummy/config/initializers/assets.rb +0 -10
  102. data/spec/dummy_engine/test/dummy/config/initializers/backtrace_silencers.rb +0 -8
  103. data/spec/dummy_engine/test/dummy/config/initializers/cookies_serializer.rb +0 -5
  104. data/spec/dummy_engine/test/dummy/config/initializers/filter_parameter_logging.rb +0 -6
  105. data/spec/dummy_engine/test/dummy/config/initializers/inflections.rb +0 -17
  106. data/spec/dummy_engine/test/dummy/config/initializers/mime_types.rb +0 -5
  107. data/spec/dummy_engine/test/dummy/config/initializers/session_store.rb +0 -5
  108. data/spec/dummy_engine/test/dummy/config/initializers/wrap_parameters.rb +0 -16
  109. data/spec/dummy_engine/test/dummy/config/locales/en.yml +0 -23
  110. data/spec/dummy_engine/test/dummy/config/routes.rb +0 -58
  111. data/spec/dummy_engine/test/dummy/config/secrets.yml +0 -22
  112. data/spec/examples/connection_adapter_examples.rb +0 -44
  113. data/spec/examples/generic_adapter_custom_configuration_example.rb +0 -93
  114. data/spec/examples/generic_adapter_examples.rb +0 -164
  115. data/spec/examples/schema_adapter_examples.rb +0 -239
  116. data/spec/integration/apartment_rake_integration_spec.rb +0 -107
  117. data/spec/integration/query_caching_spec.rb +0 -83
  118. data/spec/integration/use_within_an_engine_spec.rb +0 -28
  119. data/spec/schemas/v1.rb +0 -15
  120. data/spec/schemas/v2.rb +0 -41
  121. data/spec/schemas/v3.rb +0 -47
  122. data/spec/spec_helper.rb +0 -63
  123. data/spec/support/apartment_helpers.rb +0 -47
  124. data/spec/support/capybara_sessions.rb +0 -15
  125. data/spec/support/config.rb +0 -13
  126. data/spec/support/contexts.rb +0 -54
  127. data/spec/support/requirements.rb +0 -48
  128. data/spec/support/setup.rb +0 -46
  129. data/spec/tasks/apartment_rake_spec.rb +0 -124
  130. data/spec/tenant_spec.rb +0 -194
  131. data/spec/unit/config_spec.rb +0 -111
  132. data/spec/unit/elevators/domain_spec.rb +0 -33
  133. data/spec/unit/elevators/first_subdomain_spec.rb +0 -26
  134. data/spec/unit/elevators/generic_spec.rb +0 -55
  135. data/spec/unit/elevators/host_hash_spec.rb +0 -33
  136. data/spec/unit/elevators/host_spec.rb +0 -89
  137. data/spec/unit/elevators/subdomain_spec.rb +0 -77
  138. data/spec/unit/migrator_spec.rb +0 -78
  139. data/spec/unit/reloader_spec.rb +0 -24
@@ -39,6 +39,8 @@ module Apartment
39
39
  # Reset current tenant to the default_tenant
40
40
  #
41
41
  def reset
42
+ return unless default_tenant
43
+
42
44
  Apartment.connection.execute "use `#{default_tenant}`"
43
45
  end
44
46
 
@@ -30,6 +30,10 @@ module Apartment
30
30
  reset
31
31
  end
32
32
 
33
+ def default_tenant
34
+ @default_tenant = Apartment.default_tenant || 'public'
35
+ end
36
+
33
37
  # Reset schema search path to the default schema_search_path
34
38
  #
35
39
  # @return {String} default schema search path
@@ -37,6 +41,12 @@ module Apartment
37
41
  def reset
38
42
  @current = default_tenant
39
43
  Apartment.connection.schema_search_path = full_search_path
44
+ reset_sequence_names
45
+ end
46
+
47
+ def init
48
+ super
49
+ Apartment.connection.schema_search_path = full_search_path
40
50
  end
41
51
 
42
52
  def current
@@ -62,24 +72,30 @@ module Apartment
62
72
  #
63
73
  def connect_to_new(tenant = nil)
64
74
  return reset if tenant.nil?
65
- # rubocop:disable Style/RaiseArgs
66
- raise ActiveRecord::StatementInvalid.new("Could not find schema #{tenant}") unless Apartment.connection.schema_exists?(tenant.to_s)
67
75
 
68
- # rubocop:enable Style/RaiseArgs
76
+ tenant = tenant.to_s
77
+ raise ActiveRecord::StatementInvalid, "Could not find schema #{tenant}" unless tenant_exists?(tenant)
69
78
 
70
- @current = tenant.to_s
79
+ @current = tenant
71
80
  Apartment.connection.schema_search_path = full_search_path
72
81
 
73
82
  # When the PostgreSQL version is < 9.3,
74
83
  # there is a issue for prepared statement with changing search_path.
75
84
  # https://www.postgresql.org/docs/9.3/static/sql-prepare.html
76
85
  Apartment.connection.clear_cache! if postgresql_version < 90_300
86
+ reset_sequence_names
77
87
  rescue *rescuable_exceptions
78
88
  raise TenantNotFound, "One of the following schema(s) is invalid: \"#{tenant}\" #{full_search_path}"
79
89
  end
80
90
 
81
91
  private
82
92
 
93
+ def tenant_exists?(tenant)
94
+ return true unless Apartment.tenant_presence_check
95
+
96
+ Apartment.connection.schema_exists?(tenant)
97
+ end
98
+
83
99
  def create_tenant_command(conn, tenant)
84
100
  conn.execute(%(CREATE SCHEMA "#{tenant}"))
85
101
  end
@@ -99,6 +115,19 @@ module Apartment
99
115
  # public from Rails 5.0.
100
116
  Apartment.connection.send(:postgresql_version)
101
117
  end
118
+
119
+ def reset_sequence_names
120
+ # sequence_name contains the schema, so it must be reset after switch
121
+ # There is `reset_sequence_name`, but that method actually goes to the database
122
+ # to find out the new name. Therefore, we do this hack to only unset the name,
123
+ # and it will be dynamically found the next time it is needed
124
+ ActiveRecord::Base.descendants
125
+ .select { |c| c.instance_variable_defined?(:@sequence_name) }
126
+ .reject { |c| c.instance_variable_defined?(:@explicit_sequence_name) && c.instance_variable_get(:@explicit_sequence_name) }
127
+ .each do |c|
128
+ c.remove_instance_variable :@sequence_name
129
+ end
130
+ end
102
131
  end
103
132
 
104
133
  # Another Adapter for Postgresql when using schemas and SQL
@@ -33,6 +33,8 @@ module Apartment
33
33
  protected
34
34
 
35
35
  def connect_to_new(tenant)
36
+ return reset if tenant.nil?
37
+
36
38
  unless File.exist?(database_file(tenant))
37
39
  raise TenantNotFound,
38
40
  "The tenant #{environmentify(tenant)} cannot be found."
@@ -35,3 +35,10 @@ def tenant_list
35
35
  tenant_list += Apartment.tenant_names
36
36
  tenant_list.uniq
37
37
  end
38
+
39
+ def tenant_info_msg
40
+ # rubocop:disable Rails/Output
41
+ puts "Available Tenants: #{tenant_list}\n"
42
+ puts "Use `st 'tenant'` to switch tenants & `tenant_list` to see list\n"
43
+ # rubocop:enable Rails/Output
44
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'console'
4
+
3
5
  module Apartment
4
6
  module CustomConsole
5
7
  begin
@@ -10,17 +12,31 @@ module Apartment
10
12
  # rubocop:enable Rails/Output
11
13
  end
12
14
 
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)>'
15
+ desc = "Includes the current Rails environment and project folder name.\n" \
16
+ '[1] [project_name][Rails.env][Apartment::Tenant.current] pry(main)>'
17
+
18
+ prompt_procs = [
19
+ proc { |target_self, nest_level, pry| prompt_contents(pry, target_self, nest_level, '>') },
20
+ proc { |target_self, nest_level, pry| prompt_contents(pry, target_self, nest_level, '*') }
21
+ ]
16
22
 
23
+ if Gem::Version.new(Pry::VERSION) >= Gem::Version.new('0.13')
24
+ Pry.config.prompt = Pry::Prompt.new 'ros', desc, prompt_procs
25
+ else
17
26
  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} "
27
+ prompt_contents(pry, target_self, nest_level, sep)
21
28
  end
22
-
23
29
  Pry.config.prompt = Pry::Prompt[:ros][:value]
24
30
  end
31
+
32
+ Pry.config.hooks.add_hook(:when_started, 'startup message') do
33
+ tenant_info_msg
34
+ end
35
+
36
+ def self.prompt_contents(pry, target_self, nest_level, sep)
37
+ "[#{pry.input_ring.size}] [#{PryRails::Prompt.formatted_env}][#{Apartment::Tenant.current}] " \
38
+ "#{pry.config.prompt_name}(#{Pry.view_clip(target_self)})" \
39
+ "#{":#{nest_level}" unless nest_level.zero?}#{sep} "
40
+ end
25
41
  end
26
42
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apartment
4
+ module Model
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+ # NOTE: key can either be an array of symbols or a single value.
9
+ # E.g. If we run the following query:
10
+ # `Setting.find_by(key: 'something', value: 'amazing')` key will have an array of symbols: `[:key, :something]`
11
+ # while if we run:
12
+ # `Setting.find(10)` key will have the value 'id'
13
+ def cached_find_by_statement(key, &block)
14
+ # Modifying the cache key to have a reference to the current tenant,
15
+ # so the cached statement is referring only to the tenant in which we've
16
+ # executed this
17
+ cache_key = if key.is_a? String
18
+ "#{Apartment::Tenant.current}_#{key}"
19
+ else
20
+ [Apartment::Tenant.current] + key
21
+ end
22
+ cache = @find_by_statement_cache[connection.prepared_statements]
23
+ cache.compute_if_absent(cache_key) { ActiveRecord::StatementCache.create(connection, &block) }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -18,31 +18,35 @@ module Apartment
18
18
  config.seed_after_create = false
19
19
  config.prepend_environment = false
20
20
  config.append_environment = false
21
+ config.tenant_presence_check = true
22
+ config.active_record_log = false
21
23
  end
22
24
 
23
25
  ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a
24
26
  end
25
27
 
26
- # Hook into ActionDispatch::Reloader to ensure Apartment is properly initialized
27
- # Note that this doens't entirely work as expected in Development, because this is called before classes are reloaded
28
- # See the middleware/console declarations below to help with this. Hope to fix that soon.
29
- #
28
+ # Make sure Apartment is reconfigured when the code is reloaded
30
29
  config.to_prepare do
31
- next if ARGV.any? { |arg| arg =~ /\Aassets:(?:precompile|clean)\z/ }
32
- next if ARGV.any? { |arg| arg == 'webpacker:compile' }
30
+ Apartment::Tenant.reinitialize
31
+ end
33
32
 
34
- begin
35
- Apartment.connection_class.connection_pool.with_connection do
36
- Apartment::Tenant.init
37
- end
38
- rescue ::ActiveRecord::NoDatabaseError, PG::ConnectionBad
39
- # Since `db:create` and other tasks invoke this block from Rails 5.2.0,
40
- # we need to swallow the error to execute `db:create` properly.
41
- Rails.logger.warn do
42
- 'Failed to initialize Apartment because a database connection could not be established.'
33
+ #
34
+ # Ensure that Apartment::Tenant.init is called when
35
+ # a new connection is requested.
36
+ #
37
+ module ApartmentInitializer
38
+ def connection
39
+ super.tap do
40
+ Apartment::Tenant.init_once
43
41
  end
44
42
  end
43
+
44
+ def arel_table
45
+ Apartment::Tenant.init_once
46
+ super
47
+ end
45
48
  end
49
+ ActiveRecord::Base.singleton_class.prepend ApartmentInitializer
46
50
 
47
51
  #
48
52
  # Ensure rake tasks are loaded
@@ -0,0 +1,35 @@
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
+ # rubocop:disable Rails/Output
23
+ puts <<-WARNING
24
+ [WARNING] - The list of tenants to migrate appears to be empty. This could mean a few things:
25
+
26
+ 1. You may not have created any, in which case you can ignore this message
27
+ 2. You've run `apartment:migrate` directly without loading the Rails environment
28
+ * `apartment:migrate` is now deprecated. Tenants will automatically be migrated with `db:migrate`
29
+
30
+ Note that your tenants currently haven't been migrated. You'll need to run `db:migrate` to rectify this.
31
+ WARNING
32
+ # rubocop:enable Rails/Output
33
+ end
34
+ end
35
+ end
@@ -9,14 +9,24 @@ module Apartment
9
9
  extend self
10
10
  extend Forwardable
11
11
 
12
- def_delegators :adapter, :create, :drop, :switch, :switch!, :current, :each, :reset, :set_callback, :seed, :current_tenant, :default_tenant, :environmentify
12
+ def_delegators :adapter, :create, :drop, :switch, :switch!, :current, :each,
13
+ :reset, :init, :set_callback, :seed, :current_tenant,
14
+ :default_tenant, :environmentify
13
15
 
14
16
  attr_writer :config
15
17
 
16
- # Initialize Apartment config options such as excluded_models
17
- #
18
- def init
19
- adapter.process_excluded_models
18
+ def init_once
19
+ return if @already_initialized
20
+
21
+ # To avoid infinite loops in work init is doing,
22
+ # we need to set @already_initialized to true
23
+ # before init is called
24
+ @already_initialized = true
25
+ init
26
+ end
27
+
28
+ def reinitialize
29
+ @already_initialized = false
20
30
  end
21
31
 
22
32
  # Fetch the proper multi-tenant adapter based on Rails config
@@ -51,6 +61,7 @@ module Apartment
51
61
  #
52
62
  def reload!(config = nil)
53
63
  Thread.current[:apartment_adapter] = nil
64
+ reinitialize
54
65
  @config = config
55
66
  end
56
67
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Apartment
4
- VERSION = '2.4.0'
4
+ VERSION = '2.7.1'
5
5
  end
@@ -96,6 +96,11 @@ Apartment.configure do |config|
96
96
  # the new tenant
97
97
  #
98
98
  # config.pg_excluded_names = ["uuid_generate_v4"]
99
+
100
+ # Specifies whether the database and schema (when using PostgreSQL schemas) will prepend in ActiveRecord log.
101
+ # Uncomment the line below if you want to enable this behavior.
102
+ #
103
+ # config.active_record_log = true
99
104
  end
100
105
 
101
106
  # Setup a custom Tenant switching middleware. The Proc should return the name of the Tenant that
@@ -1,12 +1,15 @@
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
+ Apartment::TaskHelper.warn_if_tenants_empty
11
+
12
+ Apartment::TaskHelper.tenants.each do |tenant|
10
13
  begin
11
14
  puts("Creating #{tenant} tenant")
12
15
  Apartment::Tenant.create(tenant)
@@ -18,7 +21,7 @@ apartment_namespace = namespace :apartment do
18
21
 
19
22
  desc 'Drop all tenants'
20
23
  task :drop do
21
- tenants.each do |tenant|
24
+ Apartment::TaskHelper.tenants.each do |tenant|
22
25
  begin
23
26
  puts("Dropping #{tenant} tenant")
24
27
  Apartment::Tenant.drop(tenant)
@@ -30,8 +33,8 @@ apartment_namespace = namespace :apartment do
30
33
 
31
34
  desc 'Migrate all tenants'
32
35
  task :migrate do
33
- warn_if_tenants_empty
34
- each_tenant do |tenant|
36
+ Apartment::TaskHelper.warn_if_tenants_empty
37
+ Apartment::TaskHelper.each_tenant do |tenant|
35
38
  begin
36
39
  puts("Migrating #{tenant} tenant")
37
40
  Apartment::Migrator.migrate tenant
@@ -42,10 +45,10 @@ apartment_namespace = namespace :apartment do
42
45
  end
43
46
 
44
47
  desc 'Seed all tenants'
45
- task :seed do
46
- warn_if_tenants_empty
48
+ task seed: :create do
49
+ Apartment::TaskHelper.warn_if_tenants_empty
47
50
 
48
- each_tenant do |tenant|
51
+ Apartment::TaskHelper.each_tenant do |tenant|
49
52
  begin
50
53
  puts("Seeding #{tenant} tenant")
51
54
  Apartment::Tenant.switch(tenant) do
@@ -59,11 +62,11 @@ apartment_namespace = namespace :apartment do
59
62
 
60
63
  desc 'Rolls the migration back to the previous version (specify steps w/ STEP=n) across all tenants.'
61
64
  task :rollback do
62
- warn_if_tenants_empty
65
+ Apartment::TaskHelper.warn_if_tenants_empty
63
66
 
64
67
  step = ENV['STEP'] ? ENV['STEP'].to_i : 1
65
68
 
66
- each_tenant do |tenant|
69
+ Apartment::TaskHelper.each_tenant do |tenant|
67
70
  begin
68
71
  puts("Rolling back #{tenant} tenant")
69
72
  Apartment::Migrator.rollback tenant, step
@@ -76,12 +79,12 @@ apartment_namespace = namespace :apartment do
76
79
  namespace :migrate do
77
80
  desc 'Runs the "up" for a given migration VERSION across all tenants.'
78
81
  task :up do
79
- warn_if_tenants_empty
82
+ Apartment::TaskHelper.warn_if_tenants_empty
80
83
 
81
84
  version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
82
85
  raise 'VERSION is required' unless version
83
86
 
84
- each_tenant do |tenant|
87
+ Apartment::TaskHelper.each_tenant do |tenant|
85
88
  begin
86
89
  puts("Migrating #{tenant} tenant up")
87
90
  Apartment::Migrator.run :up, tenant, version
@@ -93,12 +96,12 @@ apartment_namespace = namespace :apartment do
93
96
 
94
97
  desc 'Runs the "down" for a given migration VERSION across all tenants.'
95
98
  task :down do
96
- warn_if_tenants_empty
99
+ Apartment::TaskHelper.warn_if_tenants_empty
97
100
 
98
101
  version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
99
102
  raise 'VERSION is required' unless version
100
103
 
101
- each_tenant do |tenant|
104
+ Apartment::TaskHelper.each_tenant do |tenant|
102
105
  begin
103
106
  puts("Migrating #{tenant} tenant down")
104
107
  Apartment::Migrator.run :down, tenant, version
@@ -119,28 +122,4 @@ apartment_namespace = namespace :apartment do
119
122
  end
120
123
  end
121
124
  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
125
  end