apartment 0.23.2 → 0.24.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.
- checksums.yaml +4 -4
- data/HISTORY.md +12 -1
- data/README.md +16 -13
- data/Rakefile +6 -1
- data/TODO.md +9 -14
- data/lib/apartment.rb +17 -3
- data/lib/apartment/adapters/abstract_adapter.rb +53 -44
- data/lib/apartment/adapters/jdbc_postgresql_adapter.rb +9 -9
- data/lib/apartment/adapters/mysql2_adapter.rb +15 -15
- data/lib/apartment/adapters/postgresql_adapter.rb +26 -18
- data/lib/apartment/adapters/sqlite3_adapter.rb +13 -13
- data/lib/apartment/database.rb +2 -2
- data/lib/apartment/elevators/host_hash.rb +3 -3
- data/lib/apartment/elevators/subdomain.rb +2 -3
- data/lib/apartment/migrator.rb +3 -3
- data/lib/apartment/railtie.rb +2 -1
- data/lib/apartment/tasks/enhancements.rb +26 -0
- data/lib/apartment/version.rb +1 -1
- data/lib/generators/apartment/install/templates/apartment.rb +13 -8
- data/lib/tasks/apartment.rake +34 -38
- data/spec/adapters/jdbc_mysql_adapter_spec.rb +2 -4
- data/spec/adapters/jdbc_postgresql_adapter_spec.rb +6 -6
- data/spec/adapters/mysql2_adapter_spec.rb +5 -5
- data/spec/adapters/postgresql_adapter_spec.rb +6 -6
- data/spec/adapters/sqlite3_adapter_spec.rb +2 -2
- data/spec/database_spec.rb +2 -2
- data/spec/dummy/config/initializers/apartment.rb +2 -2
- data/spec/examples/connection_adapter_examples.rb +2 -2
- data/spec/examples/generic_adapter_examples.rb +15 -15
- data/spec/examples/schema_adapter_examples.rb +6 -6
- data/spec/integration/apartment_rake_integration_spec.rb +4 -4
- data/spec/integration/query_caching_spec.rb +2 -2
- data/spec/support/requirements.rb +2 -5
- data/spec/tasks/apartment_rake_spec.rb +8 -9
- data/spec/unit/config_spec.rb +17 -10
- data/spec/unit/elevators/subdomain_spec.rb +26 -6
- metadata +3 -2
@@ -15,37 +15,37 @@ module Apartment
|
|
15
15
|
|
16
16
|
protected
|
17
17
|
|
18
|
-
# Connect to new
|
18
|
+
# Connect to new tenant
|
19
19
|
# Abstract adapter will catch generic ActiveRecord error
|
20
20
|
# Catch specific adapter errors here
|
21
21
|
#
|
22
|
-
# @param {String}
|
22
|
+
# @param {String} tenant Tenant name
|
23
23
|
#
|
24
|
-
def connect_to_new(
|
24
|
+
def connect_to_new(tenant = nil)
|
25
25
|
super
|
26
26
|
rescue Mysql2::Error
|
27
27
|
Apartment::Database.reset
|
28
|
-
raise DatabaseNotFound, "Cannot find
|
28
|
+
raise DatabaseNotFound, "Cannot find tenant #{environmentify(tenant)}"
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
class Mysql2SchemaAdapter < AbstractAdapter
|
33
|
-
attr_reader :
|
33
|
+
attr_reader :default_tenant
|
34
34
|
|
35
35
|
def initialize(config)
|
36
36
|
super
|
37
37
|
|
38
|
-
@
|
38
|
+
@default_tenant = config[:database]
|
39
39
|
reset
|
40
40
|
end
|
41
41
|
|
42
|
-
# Reset
|
42
|
+
# Reset current_tenant to the default_tenant
|
43
43
|
#
|
44
44
|
def reset
|
45
|
-
Apartment.connection.execute "use #{
|
45
|
+
Apartment.connection.execute "use #{default_tenant}"
|
46
46
|
end
|
47
47
|
|
48
|
-
# Set the table_name to always use the default
|
48
|
+
# Set the table_name to always use the default tenant for excluded models
|
49
49
|
#
|
50
50
|
def process_excluded_models
|
51
51
|
Apartment.excluded_models.each{ |model| process_excluded_model(model) }
|
@@ -53,16 +53,16 @@ module Apartment
|
|
53
53
|
|
54
54
|
protected
|
55
55
|
|
56
|
-
# Set schema
|
56
|
+
# Set schema current_tenant to new db
|
57
57
|
#
|
58
|
-
def connect_to_new(
|
59
|
-
return reset if
|
58
|
+
def connect_to_new(tenant)
|
59
|
+
return reset if tenant.nil?
|
60
60
|
|
61
|
-
Apartment.connection.execute "use #{environmentify(
|
61
|
+
Apartment.connection.execute "use #{environmentify(tenant)}"
|
62
62
|
|
63
63
|
rescue ActiveRecord::StatementInvalid
|
64
64
|
Apartment::Database.reset
|
65
|
-
raise DatabaseNotFound, "Cannot find
|
65
|
+
raise DatabaseNotFound, "Cannot find tenant #{environmentify(tenant)}"
|
66
66
|
end
|
67
67
|
|
68
68
|
def process_excluded_model(model)
|
@@ -74,7 +74,7 @@ module Apartment
|
|
74
74
|
# Ensure that if a schema *was* set, we override
|
75
75
|
table_name = klass.table_name.split('.', 2).last
|
76
76
|
|
77
|
-
klass.table_name = "#{
|
77
|
+
klass.table_name = "#{default_tenant}.#{table_name}"
|
78
78
|
end
|
79
79
|
end
|
80
80
|
end
|
@@ -14,6 +14,14 @@ module Apartment
|
|
14
14
|
# Default adapter when not using Postgresql Schemas
|
15
15
|
class PostgresqlAdapter < AbstractAdapter
|
16
16
|
|
17
|
+
def drop(tenant)
|
18
|
+
# Apartment.connection.drop_database note that drop_database will not throw an exception, so manually execute
|
19
|
+
Apartment.connection.execute(%{DROP DATABASE "#{tenant}"})
|
20
|
+
|
21
|
+
rescue *rescuable_exceptions
|
22
|
+
raise DatabaseNotFound, "The tenant #{tenant} cannot be found"
|
23
|
+
end
|
24
|
+
|
17
25
|
private
|
18
26
|
|
19
27
|
def rescue_from
|
@@ -30,15 +38,15 @@ module Apartment
|
|
30
38
|
reset
|
31
39
|
end
|
32
40
|
|
33
|
-
# Drop the
|
41
|
+
# Drop the tenant
|
34
42
|
#
|
35
|
-
# @param {String}
|
43
|
+
# @param {String} tenant Database (schema) to drop
|
36
44
|
#
|
37
|
-
def drop(
|
38
|
-
Apartment.connection.execute(%{DROP SCHEMA "#{
|
45
|
+
def drop(tenant)
|
46
|
+
Apartment.connection.execute(%{DROP SCHEMA "#{tenant}" CASCADE})
|
39
47
|
|
40
48
|
rescue *rescuable_exceptions
|
41
|
-
raise SchemaNotFound, "The schema #{
|
49
|
+
raise SchemaNotFound, "The schema #{tenant.inspect} cannot be found."
|
42
50
|
end
|
43
51
|
|
44
52
|
# Reset search path to default search_path
|
@@ -64,36 +72,36 @@ module Apartment
|
|
64
72
|
# @return {String} default schema search path
|
65
73
|
#
|
66
74
|
def reset
|
67
|
-
@
|
75
|
+
@current_tenant = Apartment.default_schema
|
68
76
|
Apartment.connection.schema_search_path = full_search_path
|
69
77
|
end
|
70
78
|
|
71
|
-
def
|
72
|
-
@
|
79
|
+
def current_tenant
|
80
|
+
@current_tenant || Apartment.default_schema
|
73
81
|
end
|
74
82
|
|
75
83
|
protected
|
76
84
|
|
77
85
|
# Set schema search path to new schema
|
78
86
|
#
|
79
|
-
def connect_to_new(
|
80
|
-
return reset if
|
81
|
-
raise ActiveRecord::StatementInvalid.new("Could not find schema #{
|
87
|
+
def connect_to_new(tenant = nil)
|
88
|
+
return reset if tenant.nil?
|
89
|
+
raise ActiveRecord::StatementInvalid.new("Could not find schema #{tenant}") unless Apartment.connection.schema_exists? tenant
|
82
90
|
|
83
|
-
@
|
91
|
+
@current_tenant = tenant.to_s
|
84
92
|
Apartment.connection.schema_search_path = full_search_path
|
85
93
|
|
86
94
|
rescue *rescuable_exceptions
|
87
|
-
raise SchemaNotFound, "One of the following schema(s) is invalid: #{
|
95
|
+
raise SchemaNotFound, "One of the following schema(s) is invalid: #{tenant}, #{full_search_path}"
|
88
96
|
end
|
89
97
|
|
90
98
|
# Create the new schema
|
91
99
|
#
|
92
|
-
def create_tenant(
|
93
|
-
Apartment.connection.execute(%{CREATE SCHEMA "#{
|
100
|
+
def create_tenant(tenant)
|
101
|
+
Apartment.connection.execute(%{CREATE SCHEMA "#{tenant}"})
|
94
102
|
|
95
103
|
rescue *rescuable_exceptions
|
96
|
-
raise SchemaExists, "The schema #{
|
104
|
+
raise SchemaExists, "The schema #{tenant} already exists."
|
97
105
|
end
|
98
106
|
|
99
107
|
private
|
@@ -103,9 +111,9 @@ module Apartment
|
|
103
111
|
def full_search_path
|
104
112
|
persistent_schemas.map(&:inspect).join(", ")
|
105
113
|
end
|
106
|
-
|
114
|
+
|
107
115
|
def persistent_schemas
|
108
|
-
[@
|
116
|
+
[@current_tenant, Apartment.persistent_schemas].flatten
|
109
117
|
end
|
110
118
|
end
|
111
119
|
end
|
@@ -15,38 +15,38 @@ module Apartment
|
|
15
15
|
super
|
16
16
|
end
|
17
17
|
|
18
|
-
def drop(
|
18
|
+
def drop(tenant)
|
19
19
|
raise DatabaseNotFound,
|
20
|
-
"The
|
20
|
+
"The tenant #{environmentify(tenant)} cannot be found." unless File.exists?(database_file(tenant))
|
21
21
|
|
22
|
-
File.delete(database_file(
|
22
|
+
File.delete(database_file(tenant))
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
25
|
+
def current_tenant
|
26
26
|
File.basename(Apartment.connection.instance_variable_get(:@config)[:database], '.sqlite3')
|
27
27
|
end
|
28
28
|
|
29
29
|
protected
|
30
30
|
|
31
|
-
def connect_to_new(
|
31
|
+
def connect_to_new(tenant)
|
32
32
|
raise DatabaseNotFound,
|
33
|
-
"The
|
33
|
+
"The tenant #{environmentify(tenant)} cannot be found." unless File.exists?(database_file(tenant))
|
34
34
|
|
35
|
-
super database_file(
|
35
|
+
super database_file(tenant)
|
36
36
|
end
|
37
37
|
|
38
|
-
def create_tenant(
|
38
|
+
def create_tenant(tenant)
|
39
39
|
raise DatabaseExists,
|
40
|
-
"The
|
40
|
+
"The tenant #{environmentify(tenant)} already exists." if File.exists?(database_file(tenant))
|
41
41
|
|
42
|
-
f = File.new(database_file(
|
42
|
+
f = File.new(database_file(tenant), File::CREAT)
|
43
43
|
f.close
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
private
|
47
47
|
|
48
|
-
def database_file(
|
49
|
-
"#{@default_dir}/#{
|
48
|
+
def database_file(tenant)
|
49
|
+
"#{@default_dir}/#{tenant}.sqlite3"
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
data/lib/apartment/database.rb
CHANGED
@@ -8,7 +8,7 @@ module Apartment
|
|
8
8
|
extend self
|
9
9
|
extend Forwardable
|
10
10
|
|
11
|
-
def_delegators :adapter, :create, :
|
11
|
+
def_delegators :adapter, :create, :current_tenant, :current, :current_database, :drop, :process, :process_excluded_models, :reset, :seed, :switch
|
12
12
|
|
13
13
|
attr_writer :config
|
14
14
|
|
@@ -63,4 +63,4 @@ module Apartment
|
|
63
63
|
@config ||= Rails.configuration.database_configuration[Rails.env].symbolize_keys
|
64
64
|
end
|
65
65
|
end
|
66
|
-
end
|
66
|
+
end
|
@@ -2,8 +2,8 @@ require 'apartment/elevators/generic'
|
|
2
2
|
|
3
3
|
module Apartment
|
4
4
|
module Elevators
|
5
|
-
# Provides a rack based
|
6
|
-
# Uses a hash to find the corresponding
|
5
|
+
# Provides a rack based tenant switching solution based on hosts
|
6
|
+
# Uses a hash to find the corresponding tenant name for the host
|
7
7
|
#
|
8
8
|
class HostHash < Generic
|
9
9
|
def initialize(app, hash = {}, processor = nil)
|
@@ -13,7 +13,7 @@ module Apartment
|
|
13
13
|
|
14
14
|
def parse_tenant_name(request)
|
15
15
|
raise DatabaseNotFound,
|
16
|
-
"Cannot find
|
16
|
+
"Cannot find tenant for host #{request.host}" unless @hash.has_key?(request.host)
|
17
17
|
|
18
18
|
@hash[request.host]
|
19
19
|
end
|
@@ -37,11 +37,10 @@ module Apartment
|
|
37
37
|
subdomains(host).first
|
38
38
|
end
|
39
39
|
|
40
|
-
|
41
|
-
def subdomains(host, tld_length = 1)
|
40
|
+
def subdomains(host)
|
42
41
|
return [] unless named_host?(host)
|
43
42
|
|
44
|
-
host.split('.')[0..-(tld_length + 2)]
|
43
|
+
host.split('.')[0..-(Apartment.tld_length + 2)]
|
45
44
|
end
|
46
45
|
|
47
46
|
def named_host?(host)
|
data/lib/apartment/migrator.rb
CHANGED
@@ -10,7 +10,7 @@ module Apartment
|
|
10
10
|
Database.process(database) do
|
11
11
|
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
12
12
|
|
13
|
-
ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.
|
13
|
+
ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, version) do |migration|
|
14
14
|
ENV["SCOPE"].blank? || (ENV["SCOPE"] == migration.scope)
|
15
15
|
end
|
16
16
|
end
|
@@ -19,14 +19,14 @@ module Apartment
|
|
19
19
|
# Migrate up/down to a specific version
|
20
20
|
def run(direction, database, version)
|
21
21
|
Database.process(database) do
|
22
|
-
ActiveRecord::Migrator.run(direction, ActiveRecord::Migrator.
|
22
|
+
ActiveRecord::Migrator.run(direction, ActiveRecord::Migrator.migrations_paths, version)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
# rollback latest migration `step` number of times
|
27
27
|
def rollback(database, step = 1)
|
28
28
|
Database.process(database) do
|
29
|
-
ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.
|
29
|
+
ActiveRecord::Migrator.rollback(ActiveRecord::Migrator.migrations_paths, step)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
data/lib/apartment/railtie.rb
CHANGED
@@ -13,10 +13,11 @@ module Apartment
|
|
13
13
|
Apartment.configure do |config|
|
14
14
|
config.excluded_models = []
|
15
15
|
config.use_schemas = true
|
16
|
-
config.
|
16
|
+
config.tenant_names = []
|
17
17
|
config.seed_after_create = false
|
18
18
|
config.prepend_environment = false
|
19
19
|
config.append_environment = false
|
20
|
+
config.tld_length = 1
|
20
21
|
end
|
21
22
|
|
22
23
|
ActiveRecord::Migrator.migrations_paths = Rails.application.paths['db/migrate'].to_a
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Require this file to append Apartment rake tasks to ActiveRecord db rake tasks
|
2
|
+
# Enabled by default in the initializer
|
3
|
+
|
4
|
+
Rake::Task["db:migrate"].enhance do
|
5
|
+
Rake::Task["apartment:migrate"].invoke
|
6
|
+
end
|
7
|
+
|
8
|
+
Rake::Task["db:rollback"].enhance do
|
9
|
+
Rake::Task["apartment:rollback"].invoke
|
10
|
+
end
|
11
|
+
|
12
|
+
Rake::Task["db:migrate:up"].enhance do
|
13
|
+
Rake::Task["apartment:migrate:up"].invoke
|
14
|
+
end
|
15
|
+
|
16
|
+
Rake::Task["db:migrate:down"].enhance do
|
17
|
+
Rake::Task["apartment:migrate:down"].invoke
|
18
|
+
end
|
19
|
+
|
20
|
+
Rake::Task["db:migrate:redo"].enhance do
|
21
|
+
Rake::Task["apartment:migrate:redo"].invoke
|
22
|
+
end
|
23
|
+
|
24
|
+
Rake::Task["db:seed"].enhance do
|
25
|
+
Rake::Task["apartment:seed"].invoke
|
26
|
+
end
|
data/lib/apartment/version.rb
CHANGED
@@ -9,13 +9,15 @@ require 'apartment/elevators/subdomain'
|
|
9
9
|
#
|
10
10
|
Apartment.configure do |config|
|
11
11
|
|
12
|
-
#
|
12
|
+
# These models will not be multi-tenanted,
|
13
13
|
# but remain in the global (public) namespace
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
}
|
14
|
+
#
|
15
|
+
# An example might be a Customer or Tenant model that stores each tenant information
|
16
|
+
# ex:
|
17
|
+
#
|
18
|
+
# config.excluded_models = %w{Tenant}
|
19
|
+
#
|
20
|
+
config.excluded_models = %w{}
|
19
21
|
|
20
22
|
# use postgres schemas?
|
21
23
|
config.use_schemas = true
|
@@ -28,8 +30,7 @@ Apartment.configure do |config|
|
|
28
30
|
# config.append_environment = true
|
29
31
|
|
30
32
|
# supply list of database names for migrations to run on
|
31
|
-
config.
|
32
|
-
|
33
|
+
config.tenant_names = lambda{ ToDo_Tenant_Or_User_Model.pluck :database }
|
33
34
|
end
|
34
35
|
|
35
36
|
##
|
@@ -42,3 +43,7 @@ end
|
|
42
43
|
# Rails.application.config.middleware.use 'Apartment::Elevators::Domain'
|
43
44
|
|
44
45
|
Rails.application.config.middleware.use 'Apartment::Elevators::Subdomain'
|
46
|
+
|
47
|
+
##
|
48
|
+
# Rake enhancements so that db:migrate etc... also runs migrations on all tenants
|
49
|
+
require 'apartment/tasks/enhancements'
|
data/lib/tasks/apartment.rake
CHANGED
@@ -2,38 +2,36 @@ require 'apartment/migrator'
|
|
2
2
|
|
3
3
|
apartment_namespace = namespace :apartment do
|
4
4
|
|
5
|
-
desc "Create all
|
6
|
-
task :
|
7
|
-
|
5
|
+
desc "Create all tenants"
|
6
|
+
task create: 'db:migrate' do
|
7
|
+
tenants.each do |tenant|
|
8
8
|
begin
|
9
|
-
puts("Creating #{
|
10
|
-
quietly { Apartment::Database.create(
|
9
|
+
puts("Creating #{tenant} tenant")
|
10
|
+
quietly { Apartment::Database.create(tenant) }
|
11
11
|
rescue Apartment::TenantExists => e
|
12
12
|
puts e.message
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
desc "Migrate all
|
18
|
-
task :migrate
|
19
|
-
|
20
|
-
database_names.each do |db|
|
17
|
+
desc "Migrate all tenants"
|
18
|
+
task :migrate do
|
19
|
+
tenants.each do |tenant|
|
21
20
|
begin
|
22
|
-
puts("Migrating #{
|
23
|
-
Apartment::Migrator.migrate
|
21
|
+
puts("Migrating #{tenant} tenant")
|
22
|
+
Apartment::Migrator.migrate tenant
|
24
23
|
rescue Apartment::TenantNotFound => e
|
25
24
|
puts e.message
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
29
28
|
|
30
|
-
desc "Seed all
|
31
|
-
task :seed
|
32
|
-
|
33
|
-
database_names.each do |db|
|
29
|
+
desc "Seed all tenants"
|
30
|
+
task :seed do
|
31
|
+
tenants.each do |tenant|
|
34
32
|
begin
|
35
|
-
puts("Seeding #{
|
36
|
-
Apartment::Database.process(
|
33
|
+
puts("Seeding #{tenant} tenant")
|
34
|
+
Apartment::Database.process(tenant) do
|
37
35
|
Apartment::Database.seed
|
38
36
|
end
|
39
37
|
rescue Apartment::TenantNotFound => e
|
@@ -42,14 +40,14 @@ apartment_namespace = namespace :apartment do
|
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
45
|
-
desc "Rolls the
|
46
|
-
task :rollback
|
43
|
+
desc "Rolls the migration back to the previous version (specify steps w/ STEP=n) across all tenants."
|
44
|
+
task :rollback do
|
47
45
|
step = ENV['STEP'] ? ENV['STEP'].to_i : 1
|
48
46
|
|
49
|
-
|
47
|
+
tenants.each do |tenant|
|
50
48
|
begin
|
51
|
-
puts("Rolling back #{
|
52
|
-
Apartment::Migrator.rollback
|
49
|
+
puts("Rolling back #{tenant} tenant")
|
50
|
+
Apartment::Migrator.rollback tenant, step
|
53
51
|
rescue Apartment::TenantNotFound => e
|
54
52
|
puts e.message
|
55
53
|
end
|
@@ -57,39 +55,38 @@ apartment_namespace = namespace :apartment do
|
|
57
55
|
end
|
58
56
|
|
59
57
|
namespace :migrate do
|
60
|
-
|
61
|
-
|
62
|
-
task :up => 'db:migrate:up' do
|
58
|
+
desc 'Runs the "up" for a given migration VERSION across all tenants.'
|
59
|
+
task :up do
|
63
60
|
version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
|
64
61
|
raise 'VERSION is required' unless version
|
65
62
|
|
66
|
-
|
63
|
+
tenants.each do |tenant|
|
67
64
|
begin
|
68
|
-
puts("Migrating #{
|
69
|
-
Apartment::Migrator.run :up,
|
65
|
+
puts("Migrating #{tenant} tenant up")
|
66
|
+
Apartment::Migrator.run :up, tenant, version
|
70
67
|
rescue Apartment::TenantNotFound => e
|
71
68
|
puts e.message
|
72
69
|
end
|
73
70
|
end
|
74
71
|
end
|
75
72
|
|
76
|
-
desc 'Runs the "down" for a given migration VERSION across all
|
77
|
-
task :down
|
73
|
+
desc 'Runs the "down" for a given migration VERSION across all tenants.'
|
74
|
+
task :down do
|
78
75
|
version = ENV['VERSION'] ? ENV['VERSION'].to_i : nil
|
79
76
|
raise 'VERSION is required' unless version
|
80
77
|
|
81
|
-
|
78
|
+
tenants.each do |tenant|
|
82
79
|
begin
|
83
|
-
puts("Migrating #{
|
84
|
-
Apartment::Migrator.run :down,
|
80
|
+
puts("Migrating #{tenant} tenant down")
|
81
|
+
Apartment::Migrator.run :down, tenant, version
|
85
82
|
rescue Apartment::TenantNotFound => e
|
86
83
|
puts e.message
|
87
84
|
end
|
88
85
|
end
|
89
86
|
end
|
90
87
|
|
91
|
-
desc '
|
92
|
-
task :redo
|
88
|
+
desc 'Rolls back the tenant one migration and re migrate up (options: STEP=x, VERSION=x).'
|
89
|
+
task :redo do
|
93
90
|
if ENV['VERSION']
|
94
91
|
apartment_namespace['migrate:down'].invoke
|
95
92
|
apartment_namespace['migrate:up'].invoke
|
@@ -98,10 +95,9 @@ apartment_namespace = namespace :apartment do
|
|
98
95
|
apartment_namespace['migrate'].invoke
|
99
96
|
end
|
100
97
|
end
|
101
|
-
|
102
98
|
end
|
103
99
|
|
104
|
-
def
|
105
|
-
ENV['DB'] ? ENV['DB'].split(',').map { |s| s.strip } : Apartment.
|
100
|
+
def tenants
|
101
|
+
ENV['DB'] ? ENV['DB'].split(',').map { |s| s.strip } : Apartment.tenant_names
|
106
102
|
end
|
107
103
|
end
|