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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e6045a554346528724708d7acfcefa45c3445f5dd1bbc184426ce13e995bbb83
4
- data.tar.gz: 5c752644fcb587efff882e8c117933147dccc5771e74c3ea3d9b967eaa33f5dc
3
+ metadata.gz: e1981c6ea91e6ef43e674e0f6d3bba9eebe8b1852f0745df774cf571c03d3c54
4
+ data.tar.gz: 4f8d4c87cdb079ec884aa3391384cae1134f025204aacbe2c4ad22a6ae204f7b
5
5
  SHA512:
6
- metadata.gz: cb160898373d824906708a959d59b40d1f76fa398b2fcdebadd57b590ddd63a3da2fcbe53eb8787a5af041f108eb27516afb27febe4aa62eb76c9a1cd7cccd4f
7
- data.tar.gz: e001ccf67a7e4891df031ee6ceb34c20f227cb3ef3499decf2e5cce59b638a76f9a8b4200c55105910a74c3f7478c11b32aeb34d8f7da481d8b388a51997b899
6
+ metadata.gz: c3258b8a167dd07e0f8f63ce0307429cd626761b4e26bb6ef3279063c119b595660613498667eafbcf5ea3eedc2f0d5603d395f14e8ec05ab1fdf9300bf2c5dc
7
+ data.tar.gz: 11e72266e807ae48685454eadbed040b586d1ddc6bc284954ae36267afc2c2ef0ae3d19dbc67408bb7d3705fb352319d2a4e8268cdf520e02910725c742f41c4
@@ -2,18 +2,27 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module Tenanted
5
- module ConnectionAdapter # :nodoc:
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
- ActiveRecord::Tenanted::DatabaseTasks.set_current_tenant if Rails.env.local?
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
- class DatabaseAdapter # :nodoc:
6
- ADAPTERS = {
7
- "sqlite3" => "ActiveRecord::Tenanted::DatabaseAdapters::SQLite",
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 = ADAPTERS[db_config.adapter]
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: #{ADAPTERS.keys.join(', ')}"
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: The Rails SQLite adapter doesn't handle directory creation for file: URIs. I would
22
- # like to fix that upstream, and remove this line.
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 { |conn| conn.tenant = tenant }
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
- module DatabaseTasks # :nodoc:
6
- extend self
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
- tenants = config.tenants.presence || [ get_current_tenant ].compact
12
- tenants.each do |tenant|
13
- tenant_config = config.new_tenant_config(tenant)
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
- def migrate_tenant(tenant_name = set_current_tenant)
19
- raise ArgumentError, "Could not find a tenanted database" unless config = base_config
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
- tenant_config = config.new_tenant_config(tenant_name)
25
+ def migrate_all
26
+ tenants.each do |tenant|
27
+ migrate_tenant(tenant)
28
+ end
29
+ end
22
30
 
23
- migrate(tenant_config)
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
- raise ArgumentError, "Could not find a tenanted database" unless config = base_config
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 base_config
37
- db_configs = ActiveRecord::Base.configurations.configs_for(
38
- env_name: ActiveRecord::Tasks::DatabaseTasks.env,
39
- include_hidden: true
40
- )
41
- db_configs.detect { |c| c.configuration_hash[:tenanted] }
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 get_current_tenant
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 = get_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
- ActiveRecord::Tasks::DatabaseTasks.send(:verbose?)
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
- prepend ActiveRecord::Tenanted::Patches::Attributes
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
- if ActiveRecord::Tenanted.connection_class
21
- # TODO: this is brittle if the key isn't tenanted ... errors in folder_for:
22
- #
23
- # NoMethodError undefined method '[]' for nil (NoMethodError) [ key[0..1], key[2..3] ].join("/")
24
- #
25
- tenant, key = key.split("/", 2)
26
- File.join(root, tenant, folder_for(key), key)
27
- else
28
- super
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
- tenant_name = tenant_name.to_s unless tenant_name == UNTENANTED_SENTINEL
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
- connection_class_for_self.connecting_to(shard: tenant_name, role: ActiveRecord.writing_role)
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
- yield
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
- prohibit_shard_swapping(prohibit_shard_swapping) do
115
- log_tenant_tag(tenant_name, &block)
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
- adapter = tenanted_root_config.new_tenant_config(tenant_name).config_adapter
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ActiveRecord
4
4
  module Tenanted
5
- VERSION = "0.5.0"
5
+ VERSION = "0.7.0"
6
6
  end
7
7
  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
- namespace :db do
4
- desc "Migrate the database for tenant ARTENANT"
5
- task "migrate:tenant" => "load_config" do
6
- unless ActiveRecord::Tenanted.connection_class
7
- warn "ActiveRecord::Tenanted integration is not configured via connection_class"
8
- next
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
- desc "Set the current tenant to ARTENANT if present, else the environment default"
60
- task "tenant" => "load_config" do
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.5.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.beta
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.beta
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.beta
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.beta
39
+ version: 8.1.2.1
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: zeitwerk
42
42
  requirement: !ruby/object:Gem::Requirement