activerecord-tenanted 0.5.0 → 0.7.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/lib/active_record/tenanted/connection_adapter.rb +15 -6
- data/lib/active_record/tenanted/console.rb +5 -1
- data/lib/active_record/tenanted/database_adapter.rb +11 -6
- data/lib/active_record/tenanted/database_configurations/tenant_config.rb +3 -3
- data/lib/active_record/tenanted/database_tasks.rb +80 -29
- data/lib/active_record/tenanted/patches.rb +12 -2
- data/lib/active_record/tenanted/railtie.rb +5 -1
- data/lib/active_record/tenanted/storage.rb +24 -9
- data/lib/active_record/tenanted/tenant.rb +23 -7
- data/lib/active_record/tenanted/untenanted_connection_pool.rb +4 -0
- data/lib/active_record/tenanted/version.rb +1 -1
- data/lib/active_record/tenanted.rb +9 -0
- data/lib/tasks/active_record/tenanted_tasks.rake +13 -71
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e1981c6ea91e6ef43e674e0f6d3bba9eebe8b1852f0745df774cf571c03d3c54
|
|
4
|
+
data.tar.gz: 4f8d4c87cdb079ec884aa3391384cae1134f025204aacbe2c4ad22a6ae204f7b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c3258b8a167dd07e0f8f63ce0307429cd626761b4e26bb6ef3279063c119b595660613498667eafbcf5ea3eedc2f0d5603d395f14e8ec05ab1fdf9300bf2c5dc
|
|
7
|
+
data.tar.gz: 11e72266e807ae48685454eadbed040b586d1ddc6bc284954ae36267afc2c2ef0ae3d19dbc67408bb7d3705fb352319d2a4e8268cdf520e02910725c742f41c4
|
|
@@ -2,18 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
module Tenanted
|
|
5
|
-
|
|
5
|
+
#
|
|
6
|
+
# Extends ActiveRecord::ConnectionAdapters::AbstractAdapter with a `tenant` attribute.
|
|
7
|
+
#
|
|
8
|
+
# This is useful in conjunction with the `:tenant` query log tag, which configures logging of
|
|
9
|
+
# the tenant in SQL query logs (when `config.active_record.query_log_tags_enabled` is set to
|
|
10
|
+
# `true`). For example:
|
|
11
|
+
#
|
|
12
|
+
# Rails.application.config.active_record.query_log_tags_enabled = true
|
|
13
|
+
# Rails.application.config.active_record.query_log_tags = [ :tenant ]
|
|
14
|
+
#
|
|
15
|
+
# will cause the application to emit logs like:
|
|
16
|
+
#
|
|
17
|
+
# User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1 /*tenant='foo'*/
|
|
18
|
+
#
|
|
19
|
+
module ConnectionAdapter
|
|
6
20
|
extend ActiveSupport::Concern
|
|
7
21
|
|
|
8
22
|
prepended do
|
|
9
23
|
attr_accessor :tenant
|
|
10
24
|
end
|
|
11
25
|
|
|
12
|
-
def log(sql, name = "SQL", binds = [], type_casted_binds = [], async: false, allow_retry: false, &block)
|
|
13
|
-
name = [ name, "[tenant=#{tenant}]" ].compact.join(" ") if tenanted?
|
|
14
|
-
super
|
|
15
|
-
end
|
|
16
|
-
|
|
17
26
|
def tenanted?
|
|
18
27
|
tenant.present?
|
|
19
28
|
end
|
|
@@ -5,7 +5,11 @@ module ActiveRecord
|
|
|
5
5
|
module Console # :nodoc:
|
|
6
6
|
module IRBConsole
|
|
7
7
|
def start
|
|
8
|
-
|
|
8
|
+
# TODO: we could be setting the current tenant for all tenanted configs.
|
|
9
|
+
if Rails.env.local? && ActiveRecord::Tenanted.connection_class
|
|
10
|
+
config = ActiveRecord::Tenanted.connection_class.connection_pool.db_config
|
|
11
|
+
ActiveRecord::Tenanted::DatabaseTasks.new(config).set_current_tenant
|
|
12
|
+
end
|
|
9
13
|
super
|
|
10
14
|
end
|
|
11
15
|
end
|
|
@@ -2,24 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
module Tenanted
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}.freeze
|
|
5
|
+
module DatabaseAdapter # :nodoc:
|
|
6
|
+
# Hash of registered database configuration adapters
|
|
7
|
+
@adapters = {}
|
|
9
8
|
|
|
10
9
|
class << self
|
|
10
|
+
def register(name, class_name)
|
|
11
|
+
@adapters[name.to_s] = class_name
|
|
12
|
+
end
|
|
13
|
+
|
|
11
14
|
def new(db_config)
|
|
12
|
-
adapter_class_name =
|
|
15
|
+
adapter_class_name = @adapters[db_config.adapter]
|
|
13
16
|
|
|
14
17
|
if adapter_class_name.nil?
|
|
15
18
|
raise ActiveRecord::Tenanted::UnsupportedDatabaseError,
|
|
16
19
|
"Unsupported database adapter for tenanting: #{db_config.adapter}. " \
|
|
17
|
-
"Supported adapters: #{
|
|
20
|
+
"Supported adapters: #{@adapters.keys.join(', ')}"
|
|
18
21
|
end
|
|
19
22
|
|
|
20
23
|
adapter_class_name.constantize.new(db_config)
|
|
21
24
|
end
|
|
22
25
|
end
|
|
26
|
+
|
|
27
|
+
register "sqlite3", "ActiveRecord::Tenanted::DatabaseAdapters::SQLite"
|
|
23
28
|
end
|
|
24
29
|
end
|
|
25
30
|
end
|
|
@@ -18,11 +18,11 @@ module ActiveRecord
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def new_connection
|
|
21
|
-
# TODO:
|
|
22
|
-
#
|
|
21
|
+
# TODO: This line can be removed once rails/rails@f1f60dc1 is in a released version of
|
|
22
|
+
# Rails, and this gem's dependency has been bumped to require that version or later.
|
|
23
23
|
config_adapter.ensure_database_directory_exists
|
|
24
24
|
|
|
25
|
-
super.tap { |
|
|
25
|
+
super.tap { |connection| connection.tenant = tenant }
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def tenanted_config_name
|
|
@@ -1,54 +1,63 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "rake"
|
|
4
|
+
|
|
3
5
|
module ActiveRecord
|
|
4
6
|
module Tenanted
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def migrate_all
|
|
9
|
-
raise ArgumentError, "Could not find a tenanted database" unless config = base_config
|
|
7
|
+
class DatabaseTasks # :nodoc:
|
|
8
|
+
include Rake::DSL
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
migrate(tenant_config)
|
|
10
|
+
class << self
|
|
11
|
+
def verbose?
|
|
12
|
+
ActiveRecord::Tasks::DatabaseTasks.send(:verbose?)
|
|
15
13
|
end
|
|
16
14
|
end
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
attr_reader :config
|
|
17
|
+
|
|
18
|
+
def initialize(config)
|
|
19
|
+
unless config.is_a?(ActiveRecord::Tenanted::DatabaseConfigurations::BaseConfig)
|
|
20
|
+
raise TypeError, "Argument must be an instance of ActiveRecord::Tenanted::DatabaseConfigurations::BaseConfig"
|
|
21
|
+
end
|
|
22
|
+
@config = config
|
|
23
|
+
end
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
def migrate_all
|
|
26
|
+
tenants.each do |tenant|
|
|
27
|
+
migrate_tenant(tenant)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
def migrate_tenant(tenant = set_current_tenant)
|
|
32
|
+
db_config = config.new_tenant_config(tenant)
|
|
33
|
+
migrate(db_config)
|
|
24
34
|
end
|
|
25
35
|
|
|
26
36
|
def drop_all
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
config.tenants.each do |tenant|
|
|
30
|
-
db_config = config.new_tenant_config(tenant)
|
|
31
|
-
db_config.config_adapter.drop_database
|
|
32
|
-
$stdout.puts "Dropped database '#{db_config.database}'" if verbose?
|
|
37
|
+
tenants.each do |tenant|
|
|
38
|
+
drop_tenant(tenant)
|
|
33
39
|
end
|
|
34
40
|
end
|
|
35
41
|
|
|
36
|
-
def
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
def drop_tenant(tenant = set_current_tenant)
|
|
43
|
+
db_config = config.new_tenant_config(tenant)
|
|
44
|
+
db_config.config_adapter.drop_database
|
|
45
|
+
$stdout.puts "Dropped database '#{db_config.database}'" if verbose?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def tenants
|
|
49
|
+
config.tenants.presence || [ get_default_tenant ].compact
|
|
42
50
|
end
|
|
43
51
|
|
|
44
|
-
def
|
|
52
|
+
def get_default_tenant
|
|
53
|
+
# TODO: needs to work with multiple tenanted configs, maybe using ENV["ARTENANT_#{config.name}"]
|
|
45
54
|
tenant = ENV["ARTENANT"]
|
|
46
55
|
|
|
47
56
|
if tenant.present?
|
|
48
57
|
$stdout.puts "Setting current tenant to #{tenant.inspect}" if verbose?
|
|
49
58
|
elsif Rails.env.local?
|
|
50
59
|
tenant = Rails.application.config.active_record_tenanted.default_tenant
|
|
51
|
-
$stdout.puts "Defaulting current tenant to #{tenant.inspect}" if verbose?
|
|
60
|
+
$stdout.puts "Defaulting current tenant for #{config.name.inspect} to #{tenant.inspect}" if verbose?
|
|
52
61
|
else
|
|
53
62
|
tenant = nil
|
|
54
63
|
$stdout.puts "Cannot determine an implicit tenant: ARTENANT not set, and Rails.env is not local." if verbose?
|
|
@@ -64,7 +73,7 @@ module ActiveRecord
|
|
|
64
73
|
end
|
|
65
74
|
|
|
66
75
|
if connection_class.current_tenant.nil?
|
|
67
|
-
connection_class.current_tenant =
|
|
76
|
+
connection_class.current_tenant = get_default_tenant
|
|
68
77
|
else
|
|
69
78
|
connection_class.current_tenant
|
|
70
79
|
end
|
|
@@ -107,7 +116,49 @@ module ActiveRecord
|
|
|
107
116
|
end
|
|
108
117
|
|
|
109
118
|
def verbose?
|
|
110
|
-
|
|
119
|
+
self.class.verbose?
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def register_rake_tasks
|
|
123
|
+
name = config.name
|
|
124
|
+
|
|
125
|
+
desc "Migrate tenanted #{name} databases for current environment"
|
|
126
|
+
task "db:migrate:#{name}" => "load_config" do
|
|
127
|
+
verbose_was = ActiveRecord::Migration.verbose
|
|
128
|
+
ActiveRecord::Migration.verbose = ActiveRecord::Tenanted::DatabaseTasks.verbose?
|
|
129
|
+
|
|
130
|
+
tenant = ENV["ARTENANT"]
|
|
131
|
+
if tenant.present?
|
|
132
|
+
migrate_tenant(tenant)
|
|
133
|
+
else
|
|
134
|
+
migrate_all
|
|
135
|
+
end
|
|
136
|
+
ensure
|
|
137
|
+
ActiveRecord::Migration.verbose = verbose_was
|
|
138
|
+
end
|
|
139
|
+
task "db:migrate" => "db:migrate:#{name}"
|
|
140
|
+
task "db:prepare" => "db:migrate:#{name}"
|
|
141
|
+
|
|
142
|
+
desc "Drop tenanted #{name} databases for current environment"
|
|
143
|
+
task "db:drop:#{name}" => "load_config" do
|
|
144
|
+
verbose_was = ActiveRecord::Migration.verbose
|
|
145
|
+
ActiveRecord::Migration.verbose = ActiveRecord::Tenanted::DatabaseTasks.verbose?
|
|
146
|
+
|
|
147
|
+
tenant = ENV["ARTENANT"]
|
|
148
|
+
if tenant.present?
|
|
149
|
+
drop_tenant(tenant)
|
|
150
|
+
else
|
|
151
|
+
drop_all
|
|
152
|
+
end
|
|
153
|
+
ensure
|
|
154
|
+
ActiveRecord::Migration.verbose = verbose_was
|
|
155
|
+
end
|
|
156
|
+
task "db:drop" => "db:drop:#{name}"
|
|
157
|
+
|
|
158
|
+
# TODO: Rails' database tasks include "db:seed" in the tasks that "db:reset" runs.
|
|
159
|
+
desc "Drop and recreate tenanted #{name} database from its schema for the current environment"
|
|
160
|
+
task "db:reset:#{name}" => [ "db:drop:#{name}", "db:migrate:#{name}" ]
|
|
161
|
+
task "db:reset" => "db:reset:#{name}"
|
|
111
162
|
end
|
|
112
163
|
end
|
|
113
164
|
end
|
|
@@ -24,8 +24,6 @@ module ActiveRecord
|
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
# TODO: This monkey patch shouldn't be necessary after 8.1 lands and the need for a
|
|
28
|
-
# connection is removed. For details see https://github.com/rails/rails/pull/54348
|
|
29
27
|
module Attributes
|
|
30
28
|
extend ActiveSupport::Concern
|
|
31
29
|
|
|
@@ -44,6 +42,18 @@ module ActiveRecord
|
|
|
44
42
|
end
|
|
45
43
|
end
|
|
46
44
|
end
|
|
45
|
+
|
|
46
|
+
class << self
|
|
47
|
+
# This monkey patch isn't necessary after 8.1 removed the need for a connection.
|
|
48
|
+
# For details see https://github.com/rails/rails/pull/54348
|
|
49
|
+
def needs_patch?
|
|
50
|
+
Gem::Requirement.new("~> 8.1.0").satisfied_by?(Gem::Version.new(Rails::VERSION::STRING))
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def apply_patch
|
|
54
|
+
ActiveRecord::Base.prepend(self) if needs_patch?
|
|
55
|
+
end
|
|
56
|
+
end
|
|
47
57
|
end
|
|
48
58
|
end
|
|
49
59
|
end
|
|
@@ -95,7 +95,7 @@ module ActiveRecord
|
|
|
95
95
|
|
|
96
96
|
initializer "active_record_tenanted.monkey_patches" do
|
|
97
97
|
ActiveSupport.on_load(:active_record) do
|
|
98
|
-
|
|
98
|
+
ActiveRecord::Tenanted::Patches::Attributes.apply_patch
|
|
99
99
|
ActiveRecord::Tasks::DatabaseTasks.prepend ActiveRecord::Tenanted::Patches::DatabaseTasks
|
|
100
100
|
end
|
|
101
101
|
end
|
|
@@ -148,6 +148,10 @@ module ActiveRecord
|
|
|
148
148
|
end
|
|
149
149
|
|
|
150
150
|
config.after_initialize do
|
|
151
|
+
ActiveRecord::QueryLogs.taggings = ActiveRecord::QueryLogs.taggings.merge(
|
|
152
|
+
tenant: ->(context) { context[:connection].tenant }
|
|
153
|
+
)
|
|
154
|
+
|
|
151
155
|
if defined?(Rails::Console)
|
|
152
156
|
require "rails/commands/console/irb_console"
|
|
153
157
|
Rails::Console::IRBConsole.prepend ActiveRecord::Tenanted::Console::IRBConsole
|
|
@@ -17,16 +17,31 @@ module ActiveRecord
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def path_for(key)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
return super unless ActiveRecord::Tenanted.connection_class && key.include?("/")
|
|
21
|
+
|
|
22
|
+
if key.split("/").intersect?(%w[. ..])
|
|
23
|
+
raise ActiveStorage::InvalidKeyError, "key has path traversal segments"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
tenant, key = key.split("/", 2)
|
|
27
|
+
|
|
28
|
+
if tenant.blank? || key.blank?
|
|
29
|
+
raise ActiveStorage::InvalidKeyError, "key has a blank segment"
|
|
29
30
|
end
|
|
31
|
+
|
|
32
|
+
begin
|
|
33
|
+
path = File.expand_path(File.join(root, tenant, folder_for(key), key))
|
|
34
|
+
rescue ArgumentError
|
|
35
|
+
raise ActiveStorage::InvalidKeyError, "key is an invalid string"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
unless path.start_with?(File.expand_path(root) + "/")
|
|
39
|
+
raise ActiveStorage::InvalidKeyError, "key is outside of disk service root"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
path
|
|
43
|
+
rescue Encoding::CompatibilityError
|
|
44
|
+
raise ActiveStorage::InvalidKeyError, "key has incompatible encoding"
|
|
30
45
|
end
|
|
31
46
|
end
|
|
32
47
|
|
|
@@ -95,9 +95,18 @@ module ActiveRecord
|
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
def current_tenant=(tenant_name)
|
|
98
|
-
|
|
98
|
+
case tenant_name
|
|
99
|
+
when nil
|
|
100
|
+
tenant_name = UNTENANTED_SENTINEL
|
|
101
|
+
when UNTENANTED_SENTINEL
|
|
102
|
+
# no-op
|
|
103
|
+
else
|
|
104
|
+
tenant_name = tenant_name.to_s
|
|
105
|
+
end
|
|
99
106
|
|
|
100
|
-
|
|
107
|
+
run_callbacks :set_current_tenant do
|
|
108
|
+
connection_class_for_self.connecting_to(shard: tenant_name, role: ActiveRecord.writing_role)
|
|
109
|
+
end
|
|
101
110
|
end
|
|
102
111
|
|
|
103
112
|
def tenant_exist?(tenant_name)
|
|
@@ -108,11 +117,13 @@ module ActiveRecord
|
|
|
108
117
|
tenant_name = tenant_name.to_s unless tenant_name == UNTENANTED_SENTINEL
|
|
109
118
|
|
|
110
119
|
if tenant_name == current_tenant
|
|
111
|
-
|
|
120
|
+
run_callbacks :with_tenant, &block
|
|
112
121
|
else
|
|
113
122
|
connection_class_for_self.connected_to(shard: tenant_name, role: ActiveRecord.writing_role) do
|
|
114
|
-
|
|
115
|
-
|
|
123
|
+
run_callbacks :with_tenant do
|
|
124
|
+
prohibit_shard_swapping(prohibit_shard_swapping) do
|
|
125
|
+
log_tenant_tag(tenant_name, &block)
|
|
126
|
+
end
|
|
116
127
|
end
|
|
117
128
|
end
|
|
118
129
|
end
|
|
@@ -120,7 +131,8 @@ module ActiveRecord
|
|
|
120
131
|
|
|
121
132
|
def create_tenant(tenant_name, if_not_exists: false, &block)
|
|
122
133
|
created_db = false
|
|
123
|
-
|
|
134
|
+
base_config = tenanted_root_config
|
|
135
|
+
adapter = base_config.new_tenant_config(tenant_name).config_adapter
|
|
124
136
|
|
|
125
137
|
adapter.acquire_ready_lock do
|
|
126
138
|
unless adapter.database_exist?
|
|
@@ -128,7 +140,7 @@ module ActiveRecord
|
|
|
128
140
|
|
|
129
141
|
with_tenant(tenant_name) do
|
|
130
142
|
connection_pool(schema_version_check: false)
|
|
131
|
-
ActiveRecord::Tenanted::DatabaseTasks.migrate_tenant(tenant_name)
|
|
143
|
+
ActiveRecord::Tenanted::DatabaseTasks.new(base_config).migrate_tenant(tenant_name)
|
|
132
144
|
end
|
|
133
145
|
|
|
134
146
|
created_db = true
|
|
@@ -254,9 +266,13 @@ module ActiveRecord
|
|
|
254
266
|
self.default_shard = ActiveRecord::Tenanted::Tenant::UNTENANTED_SENTINEL
|
|
255
267
|
|
|
256
268
|
prepend TenantCommon
|
|
269
|
+
extend ActiveSupport::Callbacks
|
|
257
270
|
|
|
258
271
|
cattr_accessor :tenanted_config_name
|
|
259
272
|
cattr_accessor(:tenanted_connection_pools) { LRU.new }
|
|
273
|
+
|
|
274
|
+
define_callbacks :with_tenant
|
|
275
|
+
define_callbacks :set_current_tenant
|
|
260
276
|
end
|
|
261
277
|
|
|
262
278
|
def tenanted?
|
|
@@ -28,6 +28,10 @@ module ActiveRecord
|
|
|
28
28
|
ActiveRecord::ConnectionAdapters::BoundSchemaReflection.new(schema_reflection, self)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
def size
|
|
32
|
+
db_config.max_connections
|
|
33
|
+
end
|
|
34
|
+
|
|
31
35
|
def lease_connection(...)
|
|
32
36
|
raise Tenanted::NoTenantError, "Cannot connect to a tenanted database while untenanted (#{@model})."
|
|
33
37
|
end
|
|
@@ -41,10 +41,19 @@ module ActiveRecord
|
|
|
41
41
|
# Raised when an unsupported database adapter is used.
|
|
42
42
|
class UnsupportedDatabaseError < Error; end
|
|
43
43
|
|
|
44
|
+
# Return the constantized connection class configured in `config.active_record_tenanted.connection_class`,
|
|
45
|
+
# or nil if none is configured.
|
|
44
46
|
def self.connection_class
|
|
45
47
|
# TODO: cache this / speed this up
|
|
46
48
|
Rails.application.config.active_record_tenanted.connection_class&.constantize
|
|
47
49
|
end
|
|
50
|
+
|
|
51
|
+
# Return an Array of the tenanted database configurations.
|
|
52
|
+
def self.base_configs(configurations = ActiveRecord::Base.configurations)
|
|
53
|
+
configurations
|
|
54
|
+
.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, include_hidden: true)
|
|
55
|
+
.select { |c| c.configuration_hash[:tenanted] }
|
|
56
|
+
end
|
|
48
57
|
end
|
|
49
58
|
end
|
|
50
59
|
|
|
@@ -1,78 +1,20 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
unless ActiveRecord::Tenanted::DatabaseTasks.base_config
|
|
12
|
-
warn "WARNING: No tenanted database found, skipping tenanted migration"
|
|
13
|
-
else
|
|
14
|
-
begin
|
|
15
|
-
verbose_was = ActiveRecord::Migration.verbose
|
|
16
|
-
ActiveRecord::Migration.verbose = ActiveRecord::Tenanted::DatabaseTasks.verbose?
|
|
17
|
-
|
|
18
|
-
ActiveRecord::Tenanted::DatabaseTasks.migrate_tenant
|
|
19
|
-
ensure
|
|
20
|
-
ActiveRecord::Migration.verbose = verbose_was
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
desc "Migrate the database for all existing tenants"
|
|
26
|
-
task "migrate:tenant:all" => "load_config" do
|
|
27
|
-
unless ActiveRecord::Tenanted.connection_class
|
|
28
|
-
warn "ActiveRecord::Tenanted integration is not configured via connection_class"
|
|
29
|
-
next
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
verbose_was = ActiveRecord::Migration.verbose
|
|
33
|
-
ActiveRecord::Migration.verbose = ActiveRecord::Tenanted::DatabaseTasks.verbose?
|
|
34
|
-
|
|
35
|
-
ActiveRecord::Tenanted::DatabaseTasks.migrate_all
|
|
36
|
-
ensure
|
|
37
|
-
ActiveRecord::Migration.verbose = verbose_was
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
desc "Drop and recreate all tenant databases from their schema for the current environment"
|
|
41
|
-
task "reset:tenant" => [ "db:drop:tenant", "db:migrate:tenant" ]
|
|
42
|
-
|
|
43
|
-
desc "Drop all tenanted databases for the current environment"
|
|
44
|
-
task "drop:tenant" => "load_config" do
|
|
45
|
-
unless ActiveRecord::Tenanted::DatabaseTasks.base_config
|
|
46
|
-
warn "WARNING: No tenanted database found, skipping tenanted reset"
|
|
47
|
-
else
|
|
48
|
-
begin
|
|
49
|
-
verbose_was = ActiveRecord::Migration.verbose
|
|
50
|
-
ActiveRecord::Migration.verbose = ActiveRecord::Tenanted::DatabaseTasks.verbose?
|
|
51
|
-
|
|
52
|
-
ActiveRecord::Tenanted::DatabaseTasks.drop_all
|
|
53
|
-
ensure
|
|
54
|
-
ActiveRecord::Migration.verbose = verbose_was
|
|
55
|
-
end
|
|
56
|
-
end
|
|
3
|
+
# Ensure a default tenant is set for database tasks that may need it.
|
|
4
|
+
desc "Set the current tenant to ARTENANT if present, else the environment default"
|
|
5
|
+
task "db:tenant" => "load_config" do
|
|
6
|
+
unless ActiveRecord::Tenanted.connection_class
|
|
7
|
+
warn "ActiveRecord::Tenanted integration is not configured via connection_class"
|
|
8
|
+
next
|
|
57
9
|
end
|
|
58
10
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
unless ActiveRecord::Tenanted.connection_class
|
|
62
|
-
warn "ActiveRecord::Tenanted integration is not configured via connection_class"
|
|
63
|
-
next
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
ActiveRecord::Tenanted::DatabaseTasks.set_current_tenant
|
|
67
|
-
end
|
|
11
|
+
config = ActiveRecord::Tenanted.connection_class.connection_pool.db_config
|
|
12
|
+
ActiveRecord::Tenanted::DatabaseTasks.new(config).set_current_tenant
|
|
68
13
|
end
|
|
69
|
-
|
|
70
|
-
# Decorate database tasks with the tenanted version.
|
|
71
|
-
task "db:migrate" => "db:migrate:tenant:all"
|
|
72
|
-
task "db:prepare" => "db:migrate:tenant:all"
|
|
73
|
-
task "db:reset" => "db:reset:tenant"
|
|
74
|
-
task "db:drop" => "db:drop:tenant"
|
|
75
|
-
|
|
76
|
-
# Ensure a default tenant is set for database tasks that may need it.
|
|
77
14
|
task "db:fixtures:load" => "db:tenant"
|
|
78
15
|
task "db:seed" => "db:tenant"
|
|
16
|
+
|
|
17
|
+
# Create tenanted rake tasks
|
|
18
|
+
ActiveRecord::Tenanted.base_configs(ActiveRecord::DatabaseConfigurations.new(ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml)).each do |config|
|
|
19
|
+
ActiveRecord::Tenanted::DatabaseTasks.new(config).register_rake_tasks
|
|
20
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: activerecord-tenanted
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mike Dalessio
|
|
@@ -15,28 +15,28 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 8.1.
|
|
18
|
+
version: 8.1.2.1
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 8.1.
|
|
25
|
+
version: 8.1.2.1
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: railties
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - ">="
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 8.1.
|
|
32
|
+
version: 8.1.2.1
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 8.1.
|
|
39
|
+
version: 8.1.2.1
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: zeitwerk
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|