Skip to content

Commit 3081fc9

Browse files
committed
Allow per-database schema format in database config
Checks the database configuration for a schema_format key, allowing applications with multilpe databases to set schema format individually for each one. Falls back to standard configuration attribute when this is not present.
1 parent 348f9b1 commit 3081fc9

File tree

11 files changed

+140
-37
lines changed

11 files changed

+140
-37
lines changed

activerecord/CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
* Allow setting `schema_format` in database configuration.
2+
3+
```
4+
primary:
5+
schema_format: ruby
6+
```
7+
8+
Useful in multi-database setups to have different formats per-database.
9+
10+
*T S Vallender*
11+
112
* Support disabling indexes for MySQL v8.0.0+ and MariaDB v10.6.0+
213
314
MySQL 8.0.0 added an option to disable indexes from being used by the query

activerecord/lib/active_record.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,8 @@ def self.permanent_connection_checkout=(value)
371371
# specific) SQL statements. If :ruby, the schema is dumped as an
372372
# ActiveRecord::Schema file which can be loaded into any database that
373373
# supports migrations. Use :ruby if you want to have different database
374-
# adapters for, e.g., your development and test environments.
374+
# adapters for, e.g., your development and test environments. This can be
375+
# overridden per-database in the database configuration.
375376
singleton_class.attr_accessor :schema_format
376377
self.schema_format = :ruby
377378

activerecord/lib/active_record/database_configurations/hash_config.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ def seeds?
146146
#
147147
# If the config option is set that will be used. Otherwise Rails will generate
148148
# the filename from the database config name.
149-
def schema_dump(format = ActiveRecord.schema_format)
149+
def schema_dump(format = schema_format)
150150
if configuration_hash.key?(:schema_dump)
151151
if config = configuration_hash[:schema_dump]
152152
config
@@ -158,6 +158,12 @@ def schema_dump(format = ActiveRecord.schema_format)
158158
end
159159
end
160160

161+
def schema_format # :nodoc:
162+
format = configuration_hash[:schema_format]&.to_sym || ActiveRecord.schema_format
163+
raise "Invalid schema format" unless [ :ruby, :sql ].include? format
164+
format
165+
end
166+
161167
def database_tasks? # :nodoc:
162168
!replica? && !!configuration_hash.fetch(:database_tasks, true)
163169
end
@@ -168,7 +174,7 @@ def use_metadata_table? # :nodoc:
168174

169175
private
170176
def schema_file_type(format)
171-
case format
177+
case format.to_sym
172178
when :ruby
173179
"schema.rb"
174180
when :sql

activerecord/lib/active_record/migration.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ def check_pending_migrations # :nodoc:
747747
private
748748
def any_schema_needs_update?
749749
!db_configs_in_current_env.all? do |db_config|
750-
Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
750+
Tasks::DatabaseTasks.schema_up_to_date?(db_config)
751751
end
752752
end
753753

activerecord/lib/active_record/railties/databases.rake

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ db_namespace = namespace :db do
454454

455455
desc "Load a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the database"
456456
task load: [:load_config, :check_protected_environments] do
457-
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
457+
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(nil, ENV["SCHEMA"])
458458
end
459459

460460
namespace :dump do
@@ -463,8 +463,7 @@ db_namespace = namespace :db do
463463
task name => :load_config do
464464
ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(name: name) do |pool|
465465
db_config = pool.db_config
466-
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
467-
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
466+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
468467
end
469468

470469
db_namespace["schema:dump:#{name}"].reenable
@@ -474,12 +473,11 @@ db_namespace = namespace :db do
474473

475474
namespace :load do
476475
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
477-
desc "Load a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the #{name} database"
476+
desc "Load a database schema file (either db/schema.rb or db/structure.sql, depending on configuration) into the #{name} database"
478477
task name => "db:test:purge:#{name}" do
479478
ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(name: name) do |pool|
480479
db_config = pool.db_config
481-
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
482-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
480+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
483481
end
484482
end
485483
end
@@ -523,13 +521,12 @@ db_namespace = namespace :db do
523521
end
524522

525523
namespace :test do
526-
# desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
524+
# desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on configuration)"
527525
task load_schema: %w(db:test:purge) do
528526
ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: "test") do |pool|
529527
db_config = pool.db_config
530528
ActiveRecord::Schema.verbose = false
531-
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
532-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
529+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
533530
end
534531
end
535532

@@ -554,8 +551,7 @@ db_namespace = namespace :db do
554551
ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: "test", name: name) do |pool|
555552
db_config = pool.db_config
556553
ActiveRecord::Schema.verbose = false
557-
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
558-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
554+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
559555
end
560556
end
561557
end

activerecord/lib/active_record/tasks/database_tasks.rb

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,8 @@ def structure_load(configuration, *arguments)
373373
database_adapter_for(db_config, *arguments).structure_load(filename, flags)
374374
end
375375

376-
def load_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
376+
def load_schema(db_config, format = db_config.schema_format, file = nil) # :nodoc:
377+
format = format.to_sym
377378
file ||= schema_dump_path(db_config, format)
378379
return unless file
379380

@@ -394,7 +395,7 @@ def load_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :n
394395
Migration.verbose = verbose_was
395396
end
396397

397-
def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil)
398+
def schema_up_to_date?(configuration, _ = nil, file = nil)
398399
db_config = resolve_configuration(configuration)
399400

400401
file ||= schema_dump_path(db_config)
@@ -410,41 +411,40 @@ def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file
410411
end
411412
end
412413

413-
def reconstruct_from_schema(db_config, format = ActiveRecord.schema_format, file = nil) # :nodoc:
414-
file ||= schema_dump_path(db_config, format)
414+
def reconstruct_from_schema(db_config, file = nil) # :nodoc:
415+
file ||= schema_dump_path(db_config, db_config.schema_format)
415416

416417
check_schema_file(file) if file
417418

418419
with_temporary_pool(db_config, clobber: true) do
419-
if schema_up_to_date?(db_config, format, file)
420+
if schema_up_to_date?(db_config, nil, file)
420421
truncate_tables(db_config) unless ENV["SKIP_TEST_DATABASE_TRUNCATE"]
421422
else
422423
purge(db_config)
423-
load_schema(db_config, format, file)
424+
load_schema(db_config, db_config.schema_format, file)
424425
end
425426
rescue ActiveRecord::NoDatabaseError
426427
create(db_config)
427-
load_schema(db_config, format, file)
428+
load_schema(db_config, db_config.schema_format, file)
428429
end
429430
end
430431

431432
def dump_all
432433
with_temporary_pool_for_each do |pool|
433434
db_config = pool.db_config
434-
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
435-
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
435+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ENV["SCHEMA_FORMAT"] || db_config.schema_format)
436436
end
437437
end
438438

439-
def dump_schema(db_config, format = ActiveRecord.schema_format) # :nodoc:
439+
def dump_schema(db_config, format = db_config.schema_format) # :nodoc:
440440
return unless db_config.schema_dump
441441

442442
require "active_record/schema_dumper"
443443
filename = schema_dump_path(db_config, format)
444444
return unless filename
445445

446446
FileUtils.mkdir_p(db_dir)
447-
case format
447+
case format.to_sym
448448
when :ruby
449449
File.open(filename, "w:utf-8") do |file|
450450
ActiveRecord::SchemaDumper.dump(migration_connection_pool, file)
@@ -460,7 +460,7 @@ def dump_schema(db_config, format = ActiveRecord.schema_format) # :nodoc:
460460
end
461461
end
462462

463-
def schema_dump_path(db_config, format = ActiveRecord.schema_format)
463+
def schema_dump_path(db_config, format = db_config.schema_format)
464464
return ENV["SCHEMA"] if ENV["SCHEMA"]
465465

466466
filename = db_config.schema_dump(format)
@@ -479,10 +479,10 @@ def cache_dump_filename(db_config, schema_cache_path: nil)
479479
db_config.default_schema_cache_path(ActiveRecord::Tasks::DatabaseTasks.db_dir)
480480
end
481481

482-
def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
482+
def load_schema_current(format = nil, file = nil, environment = env)
483483
each_current_configuration(environment) do |db_config|
484484
with_temporary_connection(db_config) do
485-
load_schema(db_config, format, file)
485+
load_schema(db_config, format || db_config.schema_format, file)
486486
end
487487
end
488488
end
@@ -669,7 +669,7 @@ def initialize_database(db_config)
669669
unless database_already_initialized
670670
schema_dump_path = schema_dump_path(db_config)
671671
if schema_dump_path && File.exist?(schema_dump_path)
672-
load_schema(db_config, ActiveRecord.schema_format, nil)
672+
load_schema(db_config)
673673
end
674674
end
675675

activerecord/lib/active_record/test_databases.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def self.create_and_load_schema(i, env_name:)
1818
ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
1919
db_config._database = "#{db_config.database}_#{i}"
2020

21-
ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord.schema_format, nil)
21+
ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, nil)
2222
end
2323
ensure
2424
ActiveRecord::Base.establish_connection

activerecord/test/cases/test_databases_test.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def test_databases_are_created
1616
base_db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
1717
expected_database = "#{base_db_config.database}_2"
1818

19-
ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _, _) {
19+
ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _) {
2020
assert_equal expected_database, db_config.database
2121
}) do
2222
ActiveRecord::TestDatabases.create_and_load_schema(2, env_name: "arunit")
@@ -39,7 +39,7 @@ def test_create_databases_after_fork
3939
base_db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
4040
expected_database = "#{base_db_config.database}_#{idx}"
4141

42-
ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _, _) {
42+
ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _) {
4343
assert_equal expected_database, db_config.database
4444
}) do
4545
ActiveSupport::Testing::Parallelization.after_fork_hooks.each { |cb| cb.call(idx) }
@@ -65,7 +65,7 @@ def test_order_of_configurations_isnt_changed_by_test_databases
6565
idx = 42
6666
base_configs_order = ActiveRecord::Base.configurations.configs_for(env_name: "arunit").map(&:name)
6767

68-
ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _, _) {
68+
ActiveRecord::Tasks::DatabaseTasks.stub(:reconstruct_from_schema, ->(db_config, _) {
6969
assert_equal base_configs_order, ActiveRecord::Base.configurations.configs_for(env_name: "arunit").map(&:name)
7070
}) do
7171
ActiveSupport::Testing::Parallelization.after_fork_hooks.each { |cb| cb.call(idx) }

guides/source/active_record_migrations.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,8 +1506,8 @@ summed up in the schema file.
15061506

15071507
The format of the schema dump generated by Rails is controlled by the
15081508
[`config.active_record.schema_format`][] setting defined in
1509-
`config/application.rb`. By default, the format is `:ruby`, or alternatively can
1510-
be set to `:sql`.
1509+
`config/application.rb`, or the `schema_format` value in the database configuration.
1510+
By default, the format is `:ruby`, or alternatively can be set to `:sql`.
15111511

15121512
#### Using the default `:ruby` schema
15131513

guides/source/configuring.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,7 @@ Determines whether to use `Time.local` (if set to `:local`) or `Time.utc` (if se
10831083
10841084
#### `config.active_record.schema_format`
10851085
1086-
Controls the format for dumping the database schema to a file. The options are `:ruby` (the default) for a database-independent version that depends on migrations, or `:sql` for a set of (potentially database-dependent) SQL statements.
1086+
Controls the format for dumping the database schema to a file. The options are `:ruby` (the default) for a database-independent version that depends on migrations, or `:sql` for a set of (potentially database-dependent) SQL statements. This can be overridden per-database by setting `schema_format` in your database configuration.
10871087
10881088
#### `config.active_record.error_on_ignored_order`
10891089

0 commit comments

Comments
 (0)