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.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +1 -1
- data/.story_branch.yml +1 -0
- data/.travis.yml +13 -30
- data/Appraisals +4 -17
- data/Gemfile +2 -2
- data/Guardfile +3 -1
- data/HISTORY.md +90 -0
- data/README.md +31 -16
- data/Rakefile +34 -22
- data/TODO.md +0 -1
- data/gemfiles/rails_5_0.gemfile +10 -11
- data/gemfiles/rails_5_1.gemfile +10 -11
- data/gemfiles/rails_5_2.gemfile +9 -10
- data/gemfiles/rails_6_0.gemfile +10 -11
- data/gemfiles/rails_master.gemfile +10 -11
- data/lib/apartment.rb +31 -13
- data/lib/apartment/active_record/connection_handling.rb +17 -0
- data/lib/apartment/active_record/internal_metadata.rb +11 -0
- data/lib/apartment/active_record/log_subscriber.rb +41 -0
- data/lib/apartment/active_record/schema_migration.rb +13 -0
- data/lib/apartment/adapters/abstract_adapter.rb +17 -13
- data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +9 -4
- data/lib/apartment/adapters/mysql2_adapter.rb +2 -0
- data/lib/apartment/adapters/postgresql_adapter.rb +33 -4
- data/lib/apartment/adapters/sqlite3_adapter.rb +2 -0
- data/lib/apartment/console.rb +7 -0
- data/lib/apartment/custom_console.rb +23 -7
- data/lib/apartment/model.rb +27 -0
- data/lib/apartment/railtie.rb +19 -15
- data/lib/apartment/tasks/task_helper.rb +35 -0
- data/lib/apartment/tenant.rb +16 -5
- data/lib/apartment/version.rb +1 -1
- data/lib/generators/apartment/install/templates/apartment.rb +5 -0
- data/lib/tasks/apartment.rake +16 -37
- data/{apartment.gemspec → ros-apartment.gemspec} +12 -6
- metadata +16 -213
- data/.github/workflows/.rubocop-linter.yml +0 -22
- data/spec/adapters/jdbc_mysql_adapter_spec.rb +0 -20
- data/spec/adapters/jdbc_postgresql_adapter_spec.rb +0 -39
- data/spec/adapters/mysql2_adapter_spec.rb +0 -61
- data/spec/adapters/postgresql_adapter_spec.rb +0 -63
- data/spec/adapters/sqlite3_adapter_spec.rb +0 -101
- data/spec/apartment_spec.rb +0 -13
- data/spec/config/database.yml.sample +0 -49
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/controllers/application_controller.rb +0 -7
- data/spec/dummy/app/helpers/application_helper.rb +0 -4
- data/spec/dummy/app/models/application_record.rb +0 -6
- data/spec/dummy/app/models/company.rb +0 -5
- data/spec/dummy/app/models/user.rb +0 -5
- data/spec/dummy/app/views/application/index.html.erb +0 -1
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/config.ru +0 -6
- data/spec/dummy/config/application.rb +0 -51
- data/spec/dummy/config/boot.rb +0 -13
- data/spec/dummy/config/database.yml.sample +0 -44
- data/spec/dummy/config/environment.rb +0 -7
- data/spec/dummy/config/environments/development.rb +0 -29
- data/spec/dummy/config/environments/production.rb +0 -53
- data/spec/dummy/config/environments/test.rb +0 -36
- data/spec/dummy/config/initializers/apartment.rb +0 -6
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -8
- data/spec/dummy/config/initializers/inflections.rb +0 -11
- data/spec/dummy/config/initializers/mime_types.rb +0 -6
- data/spec/dummy/config/initializers/secret_token.rb +0 -9
- data/spec/dummy/config/initializers/session_store.rb +0 -10
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -5
- data/spec/dummy/db/migrate/20110613152810_create_dummy_models.rb +0 -39
- data/spec/dummy/db/migrate/20111202022214_create_table_books.rb +0 -14
- data/spec/dummy/db/migrate/20180415260934_create_public_tokens.rb +0 -13
- data/spec/dummy/db/schema.rb +0 -55
- data/spec/dummy/db/seeds.rb +0 -5
- data/spec/dummy/db/seeds/import.rb +0 -7
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -26
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +0 -8
- data/spec/dummy_engine/.gitignore +0 -8
- data/spec/dummy_engine/Gemfile +0 -15
- data/spec/dummy_engine/Rakefile +0 -34
- data/spec/dummy_engine/bin/rails +0 -12
- data/spec/dummy_engine/config/initializers/apartment.rb +0 -52
- data/spec/dummy_engine/dummy_engine.gemspec +0 -24
- data/spec/dummy_engine/lib/dummy_engine.rb +0 -6
- data/spec/dummy_engine/lib/dummy_engine/engine.rb +0 -6
- data/spec/dummy_engine/lib/dummy_engine/version.rb +0 -5
- data/spec/dummy_engine/test/dummy/Rakefile +0 -6
- data/spec/dummy_engine/test/dummy/config.ru +0 -6
- data/spec/dummy_engine/test/dummy/config/application.rb +0 -24
- data/spec/dummy_engine/test/dummy/config/boot.rb +0 -7
- data/spec/dummy_engine/test/dummy/config/database.yml +0 -25
- data/spec/dummy_engine/test/dummy/config/environment.rb +0 -7
- data/spec/dummy_engine/test/dummy/config/environments/development.rb +0 -39
- data/spec/dummy_engine/test/dummy/config/environments/production.rb +0 -80
- data/spec/dummy_engine/test/dummy/config/environments/test.rb +0 -41
- data/spec/dummy_engine/test/dummy/config/initializers/assets.rb +0 -10
- data/spec/dummy_engine/test/dummy/config/initializers/backtrace_silencers.rb +0 -8
- data/spec/dummy_engine/test/dummy/config/initializers/cookies_serializer.rb +0 -5
- data/spec/dummy_engine/test/dummy/config/initializers/filter_parameter_logging.rb +0 -6
- data/spec/dummy_engine/test/dummy/config/initializers/inflections.rb +0 -17
- data/spec/dummy_engine/test/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy_engine/test/dummy/config/initializers/session_store.rb +0 -5
- data/spec/dummy_engine/test/dummy/config/initializers/wrap_parameters.rb +0 -16
- data/spec/dummy_engine/test/dummy/config/locales/en.yml +0 -23
- data/spec/dummy_engine/test/dummy/config/routes.rb +0 -58
- data/spec/dummy_engine/test/dummy/config/secrets.yml +0 -22
- data/spec/examples/connection_adapter_examples.rb +0 -44
- data/spec/examples/generic_adapter_custom_configuration_example.rb +0 -93
- data/spec/examples/generic_adapter_examples.rb +0 -164
- data/spec/examples/schema_adapter_examples.rb +0 -239
- data/spec/integration/apartment_rake_integration_spec.rb +0 -107
- data/spec/integration/query_caching_spec.rb +0 -83
- data/spec/integration/use_within_an_engine_spec.rb +0 -28
- data/spec/schemas/v1.rb +0 -15
- data/spec/schemas/v2.rb +0 -41
- data/spec/schemas/v3.rb +0 -47
- data/spec/spec_helper.rb +0 -63
- data/spec/support/apartment_helpers.rb +0 -47
- data/spec/support/capybara_sessions.rb +0 -15
- data/spec/support/config.rb +0 -13
- data/spec/support/contexts.rb +0 -54
- data/spec/support/requirements.rb +0 -48
- data/spec/support/setup.rb +0 -46
- data/spec/tasks/apartment_rake_spec.rb +0 -124
- data/spec/tenant_spec.rb +0 -194
- data/spec/unit/config_spec.rb +0 -111
- data/spec/unit/elevators/domain_spec.rb +0 -33
- data/spec/unit/elevators/first_subdomain_spec.rb +0 -26
- data/spec/unit/elevators/generic_spec.rb +0 -55
- data/spec/unit/elevators/host_hash_spec.rb +0 -33
- data/spec/unit/elevators/host_spec.rb +0 -89
- data/spec/unit/elevators/subdomain_spec.rb +0 -77
- data/spec/unit/migrator_spec.rb +0 -78
- data/spec/unit/reloader_spec.rb +0 -24
@@ -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
|
-
|
76
|
+
tenant = tenant.to_s
|
77
|
+
raise ActiveRecord::StatementInvalid, "Could not find schema #{tenant}" unless tenant_exists?(tenant)
|
69
78
|
|
70
|
-
@current = tenant
|
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
|
data/lib/apartment/console.rb
CHANGED
@@ -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
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
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
|
data/lib/apartment/railtie.rb
CHANGED
@@ -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
|
-
#
|
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
|
-
|
32
|
-
|
30
|
+
Apartment::Tenant.reinitialize
|
31
|
+
end
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
data/lib/apartment/tenant.rb
CHANGED
@@ -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,
|
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
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
|
data/lib/apartment/version.rb
CHANGED
@@ -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
|
data/lib/tasks/apartment.rake
CHANGED
@@ -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
|
-
|
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 :
|
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
|