activerecord 7.1.5.1 → 7.2.0.beta1
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/CHANGELOG.md +515 -2445
- data/README.rdoc +15 -15
- data/examples/performance.rb +2 -2
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +9 -8
- data/lib/active_record/associations/belongs_to_association.rb +14 -7
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/belongs_to.rb +1 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/collection_association.rb +6 -4
- data/lib/active_record/associations/collection_proxy.rb +14 -1
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +29 -28
- data/lib/active_record/associations/join_dependency.rb +5 -5
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +2 -1
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +1 -3
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +33 -16
- data/lib/active_record/attribute_assignment.rb +1 -11
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +1 -1
- data/lib/active_record/attribute_methods/primary_key.rb +23 -55
- data/lib/active_record/attribute_methods/read.rb +4 -16
- data/lib/active_record/attribute_methods/serialization.rb +4 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -10
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +60 -71
- data/lib/active_record/attributes.rb +55 -42
- data/lib/active_record/autosave_association.rb +13 -32
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +248 -65
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +34 -17
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +159 -74
- data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/transaction.rb +60 -57
- data/lib/active_record/connection_adapters/abstract_adapter.rb +18 -46
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +32 -6
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
- data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +7 -1
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +11 -5
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +5 -23
- data/lib/active_record/connection_adapters/pool_config.rb +7 -6
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +15 -13
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +26 -21
- data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
- data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +44 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +25 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +107 -75
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +12 -6
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +19 -48
- data/lib/active_record/connection_adapters.rb +121 -0
- data/lib/active_record/connection_handling.rb +56 -41
- data/lib/active_record/core.rb +53 -37
- data/lib/active_record/counter_cache.rb +18 -9
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
- data/lib/active_record/database_configurations/database_config.rb +15 -4
- data/lib/active_record/database_configurations/hash_config.rb +38 -34
- data/lib/active_record/database_configurations/url_config.rb +20 -1
- data/lib/active_record/database_configurations.rb +1 -1
- data/lib/active_record/delegated_type.rb +24 -0
- data/lib/active_record/dynamic_matchers.rb +2 -2
- data/lib/active_record/encryption/encryptable_record.rb +2 -2
- data/lib/active_record/encryption/encrypted_attribute_type.rb +22 -2
- data/lib/active_record/encryption/encryptor.rb +17 -2
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +4 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption.rb +0 -2
- data/lib/active_record/enum.rb +10 -1
- data/lib/active_record/errors.rb +16 -11
- data/lib/active_record/explain.rb +13 -24
- data/lib/active_record/fixtures.rb +37 -31
- data/lib/active_record/future_result.rb +8 -4
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +4 -2
- data/lib/active_record/insert_all.rb +18 -15
- data/lib/active_record/integration.rb +4 -1
- data/lib/active_record/internal_metadata.rb +48 -34
- data/lib/active_record/locking/optimistic.rb +7 -6
- data/lib/active_record/log_subscriber.rb +0 -21
- data/lib/active_record/marshalling.rb +1 -4
- data/lib/active_record/message_pack.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +2 -3
- data/lib/active_record/migration/compatibility.rb +5 -3
- data/lib/active_record/migration/default_strategy.rb +4 -5
- data/lib/active_record/migration/pending_migration_connection.rb +2 -2
- data/lib/active_record/migration.rb +85 -76
- data/lib/active_record/model_schema.rb +28 -68
- data/lib/active_record/nested_attributes.rb +13 -16
- data/lib/active_record/normalization.rb +3 -7
- data/lib/active_record/persistence.rb +30 -352
- data/lib/active_record/query_cache.rb +18 -6
- data/lib/active_record/query_logs.rb +15 -0
- data/lib/active_record/querying.rb +21 -9
- data/lib/active_record/railtie.rb +50 -62
- data/lib/active_record/railties/controller_runtime.rb +13 -4
- data/lib/active_record/railties/databases.rake +41 -44
- data/lib/active_record/reflection.rb +90 -35
- data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +94 -61
- data/lib/active_record/relation/delegation.rb +8 -11
- data/lib/active_record/relation/finder_methods.rb +16 -2
- data/lib/active_record/relation/merger.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder.rb +3 -3
- data/lib/active_record/relation/query_methods.rb +196 -57
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +2 -18
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +496 -72
- data/lib/active_record/result.rb +31 -44
- data/lib/active_record/runtime_registry.rb +39 -0
- data/lib/active_record/sanitization.rb +24 -19
- data/lib/active_record/schema.rb +8 -6
- data/lib/active_record/schema_dumper.rb +19 -9
- data/lib/active_record/schema_migration.rb +30 -14
- data/lib/active_record/signed_id.rb +11 -1
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/table_metadata.rb +1 -10
- data/lib/active_record/tasks/database_tasks.rb +76 -70
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
- data/lib/active_record/test_fixtures.rb +81 -91
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +1 -1
- data/lib/active_record/token_for.rb +22 -12
- data/lib/active_record/touch_later.rb +1 -1
- data/lib/active_record/transaction.rb +68 -0
- data/lib/active_record/transactions.rb +43 -14
- data/lib/active_record/translation.rb +0 -2
- data/lib/active_record/type/serialized.rb +1 -3
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/associated.rb +9 -3
- data/lib/active_record/validations/uniqueness.rb +14 -10
- data/lib/active_record/validations.rb +4 -1
- data/lib/active_record.rb +149 -40
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/nodes/binary.rb +0 -6
- data/lib/arel/nodes/bound_sql_literal.rb +9 -5
- data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
- data/lib/arel/nodes/node.rb +4 -3
- data/lib/arel/nodes/sql_literal.rb +7 -0
- data/lib/arel/nodes.rb +2 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/tree_manager.rb +3 -2
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +9 -4
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/to_sql.rb +29 -16
- data/lib/arel.rb +7 -3
- metadata +20 -15
@@ -125,11 +125,11 @@ module ActiveRecord
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def create_all
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
128
|
+
db_config = migration_connection.pool.db_config
|
129
|
+
|
130
|
+
each_local_configuration { |db_config| create(db_config) }
|
131
|
+
|
132
|
+
migration_class.establish_connection(db_config)
|
133
133
|
end
|
134
134
|
|
135
135
|
def setup_initial_database_yaml # :nodoc:
|
@@ -175,12 +175,11 @@ module ActiveRecord
|
|
175
175
|
|
176
176
|
def prepare_all
|
177
177
|
seed = false
|
178
|
-
dump_db_configs = []
|
179
178
|
|
180
179
|
each_current_configuration(env) do |db_config|
|
181
180
|
with_temporary_pool(db_config) do
|
182
181
|
begin
|
183
|
-
database_initialized =
|
182
|
+
database_initialized = migration_connection_pool.schema_migration.table_exists?
|
184
183
|
rescue ActiveRecord::NoDatabaseError
|
185
184
|
create(db_config)
|
186
185
|
retry
|
@@ -193,27 +192,9 @@ module ActiveRecord
|
|
193
192
|
|
194
193
|
seed = true
|
195
194
|
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
each_current_environment(env) do |environment|
|
200
|
-
db_configs_with_versions(environment).sort.each do |version, db_configs|
|
201
|
-
dump_db_configs |= db_configs
|
202
|
-
|
203
|
-
db_configs.each do |db_config|
|
204
|
-
with_temporary_pool(db_config) do
|
205
|
-
migrate(version)
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
195
|
|
211
|
-
|
212
|
-
|
213
|
-
dump_db_configs.each do |db_config|
|
214
|
-
with_temporary_pool(db_config) do
|
215
|
-
dump_schema(db_config)
|
216
|
-
end
|
196
|
+
migrate
|
197
|
+
dump_schema(db_config) if ActiveRecord.dump_schema_after_migration
|
217
198
|
end
|
218
199
|
end
|
219
200
|
|
@@ -259,7 +240,7 @@ module ActiveRecord
|
|
259
240
|
|
260
241
|
check_target_version
|
261
242
|
|
262
|
-
|
243
|
+
migration_connection_pool.migration_context.migrate(target_version) do |migration|
|
263
244
|
if version.blank?
|
264
245
|
scope.blank? || scope == migration.scope
|
265
246
|
else
|
@@ -269,17 +250,17 @@ module ActiveRecord
|
|
269
250
|
Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
|
270
251
|
end
|
271
252
|
|
272
|
-
|
253
|
+
migration_connection_pool.schema_cache.clear!
|
273
254
|
ensure
|
274
255
|
Migration.verbose = verbose_was
|
275
256
|
end
|
276
257
|
|
277
|
-
def db_configs_with_versions
|
258
|
+
def db_configs_with_versions # :nodoc:
|
278
259
|
db_configs_with_versions = Hash.new { |h, k| h[k] = [] }
|
279
260
|
|
280
|
-
|
281
|
-
db_config =
|
282
|
-
versions_to_run =
|
261
|
+
with_temporary_pool_for_each do |pool|
|
262
|
+
db_config = pool.db_config
|
263
|
+
versions_to_run = pool.migration_context.pending_migration_versions
|
283
264
|
target_version = ActiveRecord::Tasks::DatabaseTasks.target_version
|
284
265
|
|
285
266
|
versions_to_run.each do |version|
|
@@ -292,15 +273,15 @@ module ActiveRecord
|
|
292
273
|
end
|
293
274
|
|
294
275
|
def migrate_status
|
295
|
-
unless
|
276
|
+
unless migration_connection_pool.schema_migration.table_exists?
|
296
277
|
Kernel.abort "Schema migrations table does not exist yet."
|
297
278
|
end
|
298
279
|
|
299
280
|
# output
|
300
|
-
puts "\ndatabase: #{
|
281
|
+
puts "\ndatabase: #{migration_connection_pool.db_config.database}\n\n"
|
301
282
|
puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
|
302
283
|
puts "-" * 50
|
303
|
-
|
284
|
+
migration_connection_pool.migration_context.migrations_status.each do |status, version, name|
|
304
285
|
puts "#{status.center(8)} #{version.ljust(14)} #{name}"
|
305
286
|
end
|
306
287
|
puts
|
@@ -381,7 +362,7 @@ module ActiveRecord
|
|
381
362
|
raise ArgumentError, "unknown format #{format.inspect}"
|
382
363
|
end
|
383
364
|
|
384
|
-
|
365
|
+
migration_connection_pool.internal_metadata.create_table_and_set_flags(db_config.env_name, schema_sha1(file))
|
385
366
|
ensure
|
386
367
|
Migration.verbose = verbose_was
|
387
368
|
end
|
@@ -393,11 +374,12 @@ module ActiveRecord
|
|
393
374
|
|
394
375
|
return true unless file && File.exist?(file)
|
395
376
|
|
396
|
-
|
397
|
-
|
398
|
-
return false unless
|
377
|
+
with_temporary_pool(db_config) do |pool|
|
378
|
+
internal_metadata = pool.internal_metadata
|
379
|
+
return false unless internal_metadata.enabled?
|
380
|
+
return false unless internal_metadata.table_exists?
|
399
381
|
|
400
|
-
|
382
|
+
internal_metadata[:schema_sha1] == schema_sha1(file)
|
401
383
|
end
|
402
384
|
end
|
403
385
|
|
@@ -408,7 +390,7 @@ module ActiveRecord
|
|
408
390
|
|
409
391
|
with_temporary_pool(db_config, clobber: true) do
|
410
392
|
if schema_up_to_date?(db_config, format, file)
|
411
|
-
truncate_tables(db_config)
|
393
|
+
truncate_tables(db_config) unless ENV["SKIP_TEST_DATABASE_TRUNCATE"]
|
412
394
|
else
|
413
395
|
purge(db_config)
|
414
396
|
load_schema(db_config, format, file)
|
@@ -430,11 +412,11 @@ module ActiveRecord
|
|
430
412
|
case format
|
431
413
|
when :ruby
|
432
414
|
File.open(filename, "w:utf-8") do |file|
|
433
|
-
ActiveRecord::SchemaDumper.dump(
|
415
|
+
ActiveRecord::SchemaDumper.dump(migration_connection_pool, file)
|
434
416
|
end
|
435
417
|
when :sql
|
436
418
|
structure_dump(db_config, filename)
|
437
|
-
if
|
419
|
+
if migration_connection_pool.schema_migration.table_exists?
|
438
420
|
File.open(filename, "a") do |f|
|
439
421
|
f.puts migration_connection.dump_schema_information
|
440
422
|
f.print "\n"
|
@@ -456,14 +438,26 @@ module ActiveRecord
|
|
456
438
|
end
|
457
439
|
end
|
458
440
|
|
459
|
-
def cache_dump_filename(
|
460
|
-
|
461
|
-
|
441
|
+
def cache_dump_filename(db_config_or_name, schema_cache_path: nil)
|
442
|
+
if db_config_or_name.is_a?(DatabaseConfigurations::DatabaseConfig)
|
443
|
+
schema_cache_path ||
|
444
|
+
db_config_or_name.schema_cache_path ||
|
445
|
+
schema_cache_env ||
|
446
|
+
db_config_or_name.default_schema_cache_path(ActiveRecord::Tasks::DatabaseTasks.db_dir)
|
462
447
|
else
|
463
|
-
|
464
|
-
|
448
|
+
ActiveRecord.deprecator.warn(<<~MSG.squish)
|
449
|
+
Passing a database name to `cache_dump_filename` is deprecated and will be removed in Rails 7.3. Pass a
|
450
|
+
`ActiveRecord::DatabaseConfigurations::DatabaseConfig` object instead.
|
451
|
+
MSG
|
465
452
|
|
466
|
-
|
453
|
+
filename = if ActiveRecord::Base.configurations.primary?(db_config_or_name)
|
454
|
+
"schema_cache.yml"
|
455
|
+
else
|
456
|
+
"#{db_config_or_name}_schema_cache.yml"
|
457
|
+
end
|
458
|
+
|
459
|
+
schema_cache_path || schema_cache_env || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
|
460
|
+
end
|
467
461
|
end
|
468
462
|
|
469
463
|
def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
|
@@ -495,29 +489,29 @@ module ActiveRecord
|
|
495
489
|
# Dumps the schema cache in YAML format for the connection into the file
|
496
490
|
#
|
497
491
|
# ==== Examples
|
498
|
-
# ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.
|
499
|
-
def dump_schema_cache(
|
500
|
-
|
492
|
+
# ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.lease_connection, "tmp/schema_dump.yaml")
|
493
|
+
def dump_schema_cache(conn_or_pool, filename)
|
494
|
+
conn_or_pool.schema_cache.dump_to(filename)
|
501
495
|
end
|
502
496
|
|
503
497
|
def clear_schema_cache(filename)
|
504
498
|
FileUtils.rm_f filename, verbose: false
|
505
499
|
end
|
506
500
|
|
507
|
-
def
|
501
|
+
def with_temporary_pool_for_each(env: ActiveRecord::Tasks::DatabaseTasks.env, name: nil, clobber: false, &block) # :nodoc:
|
508
502
|
if name
|
509
503
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: env, name: name)
|
510
|
-
|
504
|
+
with_temporary_pool(db_config, clobber: clobber, &block)
|
511
505
|
else
|
512
506
|
ActiveRecord::Base.configurations.configs_for(env_name: env, name: name).each do |db_config|
|
513
|
-
|
507
|
+
with_temporary_pool(db_config, clobber: clobber, &block)
|
514
508
|
end
|
515
509
|
end
|
516
510
|
end
|
517
511
|
|
518
|
-
def with_temporary_connection(db_config, clobber: false) # :nodoc:
|
512
|
+
def with_temporary_connection(db_config, clobber: false, &block) # :nodoc:
|
519
513
|
with_temporary_pool(db_config, clobber: clobber) do |pool|
|
520
|
-
|
514
|
+
pool.with_connection(&block)
|
521
515
|
end
|
522
516
|
end
|
523
517
|
|
@@ -526,10 +520,25 @@ module ActiveRecord
|
|
526
520
|
end
|
527
521
|
|
528
522
|
def migration_connection # :nodoc:
|
529
|
-
migration_class.
|
523
|
+
migration_class.lease_connection
|
524
|
+
end
|
525
|
+
|
526
|
+
def migration_connection_pool # :nodoc:
|
527
|
+
migration_class.connection_pool
|
530
528
|
end
|
531
529
|
|
532
530
|
private
|
531
|
+
def schema_cache_env
|
532
|
+
if ENV["SCHEMA_CACHE"]
|
533
|
+
ActiveRecord.deprecator.warn(<<~MSG.squish)
|
534
|
+
Setting `ENV["SCHEMA_CACHE"]` is deprecated and will be removed in Rails 7.3.
|
535
|
+
Configure the `:schema_cache_path` in the database configuration instead.
|
536
|
+
MSG
|
537
|
+
|
538
|
+
nil
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
533
542
|
def with_temporary_pool(db_config, clobber: false)
|
534
543
|
original_db_config = migration_class.connection_db_config
|
535
544
|
pool = migration_class.connection_handler.establish_connection(db_config, clobber: clobber)
|
@@ -571,7 +580,10 @@ module ActiveRecord
|
|
571
580
|
end
|
572
581
|
|
573
582
|
def each_current_configuration(environment, name = nil)
|
574
|
-
|
583
|
+
environments = [environment]
|
584
|
+
environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
|
585
|
+
|
586
|
+
environments.each do |env|
|
575
587
|
configs_for(env_name: env).each do |db_config|
|
576
588
|
next if name && name != db_config.name
|
577
589
|
|
@@ -580,12 +592,6 @@ module ActiveRecord
|
|
580
592
|
end
|
581
593
|
end
|
582
594
|
|
583
|
-
def each_current_environment(environment, &block)
|
584
|
-
environments = [environment]
|
585
|
-
environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
|
586
|
-
environments.each(&block)
|
587
|
-
end
|
588
|
-
|
589
595
|
def each_local_configuration
|
590
596
|
configs_for.each do |db_config|
|
591
597
|
next unless db_config.database
|
@@ -625,11 +631,11 @@ module ActiveRecord
|
|
625
631
|
|
626
632
|
def check_current_protected_environment!(db_config)
|
627
633
|
with_temporary_pool(db_config) do |pool|
|
628
|
-
|
629
|
-
current =
|
630
|
-
stored =
|
634
|
+
migration_context = pool.migration_context
|
635
|
+
current = migration_context.current_environment
|
636
|
+
stored = migration_context.last_stored_environment
|
631
637
|
|
632
|
-
if
|
638
|
+
if migration_context.protected_environment?
|
633
639
|
raise ActiveRecord::ProtectedEnvironmentError.new(stored)
|
634
640
|
end
|
635
641
|
|
@@ -66,11 +66,12 @@ module ActiveRecord
|
|
66
66
|
attr_reader :db_config, :root
|
67
67
|
|
68
68
|
def connection
|
69
|
-
ActiveRecord::Base.
|
69
|
+
ActiveRecord::Base.lease_connection
|
70
70
|
end
|
71
71
|
|
72
72
|
def establish_connection(config = db_config)
|
73
73
|
ActiveRecord::Base.establish_connection(config)
|
74
|
+
connection.connect!
|
74
75
|
end
|
75
76
|
|
76
77
|
def run_cmd(cmd, args, out)
|
@@ -53,20 +53,6 @@ module ActiveRecord
|
|
53
53
|
self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
|
54
54
|
end
|
55
55
|
|
56
|
-
def fixture_path # :nodoc:
|
57
|
-
ActiveRecord.deprecator.warn(<<~WARNING)
|
58
|
-
TestFixtures.fixture_path is deprecated and will be removed in Rails 7.2. Use .fixture_paths instead.
|
59
|
-
If multiple fixture paths have been configured with .fixture_paths, then .fixture_path will just return
|
60
|
-
the first path.
|
61
|
-
WARNING
|
62
|
-
fixture_paths.first
|
63
|
-
end
|
64
|
-
|
65
|
-
def fixture_path=(path) # :nodoc:
|
66
|
-
ActiveRecord.deprecator.warn("TestFixtures.fixture_path= is deprecated and will be removed in Rails 7.2. Use .fixture_paths= instead.")
|
67
|
-
self.fixture_paths = Array(path)
|
68
|
-
end
|
69
|
-
|
70
56
|
def fixtures(*fixture_set_names)
|
71
57
|
if fixture_set_names.first == :all
|
72
58
|
raise StandardError, "No fixture path found. Please set `#{self}.fixture_paths`." if fixture_paths.blank?
|
@@ -79,7 +65,7 @@ module ActiveRecord
|
|
79
65
|
fixture_set_names = fixture_set_names.flatten.map(&:to_s)
|
80
66
|
end
|
81
67
|
|
82
|
-
self.fixture_table_names
|
68
|
+
self.fixture_table_names = (fixture_table_names | fixture_set_names).sort
|
83
69
|
setup_fixture_accessors(fixture_set_names)
|
84
70
|
end
|
85
71
|
|
@@ -110,45 +96,68 @@ module ActiveRecord
|
|
110
96
|
end
|
111
97
|
end
|
112
98
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
the first path.
|
118
|
-
WARNING
|
119
|
-
fixture_paths.first
|
120
|
-
end
|
121
|
-
|
122
|
-
def run_in_transaction?
|
123
|
-
use_transactional_tests &&
|
124
|
-
!self.class.uses_transaction?(name)
|
125
|
-
end
|
126
|
-
|
127
|
-
def setup_fixtures(config = ActiveRecord::Base)
|
128
|
-
if pre_loaded_fixtures && !use_transactional_tests
|
129
|
-
raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
|
99
|
+
private
|
100
|
+
def run_in_transaction?
|
101
|
+
use_transactional_tests &&
|
102
|
+
!self.class.uses_transaction?(name)
|
130
103
|
end
|
131
104
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
@saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
105
|
+
def setup_fixtures(config = ActiveRecord::Base)
|
106
|
+
if pre_loaded_fixtures && !use_transactional_tests
|
107
|
+
raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
|
108
|
+
end
|
137
109
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
110
|
+
@fixture_cache = {}
|
111
|
+
@fixture_cache_key = [self.class.fixture_table_names.dup, self.class.fixture_paths.dup, self.class.fixture_class_names.dup]
|
112
|
+
@fixture_connection_pools = []
|
113
|
+
@@already_loaded_fixtures ||= {}
|
114
|
+
@connection_subscriber = nil
|
115
|
+
@saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
|
116
|
+
|
117
|
+
if run_in_transaction?
|
118
|
+
# Load fixtures once and begin transaction.
|
119
|
+
@loaded_fixtures = @@already_loaded_fixtures[@fixture_cache_key]
|
120
|
+
unless @loaded_fixtures
|
121
|
+
@@already_loaded_fixtures.clear
|
122
|
+
@loaded_fixtures = @@already_loaded_fixtures[@fixture_cache_key] = load_fixtures(config)
|
123
|
+
end
|
124
|
+
|
125
|
+
setup_transactional_fixtures
|
142
126
|
else
|
127
|
+
# Load fixtures for every test.
|
128
|
+
ActiveRecord::FixtureSet.reset_cache
|
129
|
+
invalidate_already_loaded_fixtures
|
143
130
|
@loaded_fixtures = load_fixtures(config)
|
144
|
-
@@already_loaded_fixtures[self.class] = @loaded_fixtures
|
145
131
|
end
|
146
132
|
|
133
|
+
# Instantiate fixtures for every test if requested.
|
134
|
+
instantiate_fixtures if use_instantiated_fixtures
|
135
|
+
end
|
136
|
+
|
137
|
+
def teardown_fixtures
|
138
|
+
# Rollback changes if a transaction is active.
|
139
|
+
if run_in_transaction?
|
140
|
+
teardown_transactional_fixtures
|
141
|
+
else
|
142
|
+
ActiveRecord::FixtureSet.reset_cache
|
143
|
+
invalidate_already_loaded_fixtures
|
144
|
+
end
|
145
|
+
|
146
|
+
ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
|
147
|
+
end
|
148
|
+
|
149
|
+
def invalidate_already_loaded_fixtures
|
150
|
+
@@already_loaded_fixtures.clear
|
151
|
+
end
|
152
|
+
|
153
|
+
def setup_transactional_fixtures
|
154
|
+
setup_shared_connection_pool
|
155
|
+
|
147
156
|
# Begin transactions for connections already established
|
148
|
-
@
|
149
|
-
@
|
150
|
-
|
151
|
-
|
157
|
+
@fixture_connection_pools = ActiveRecord::Base.connection_handler.connection_pool_list(:writing)
|
158
|
+
@fixture_connection_pools.each do |pool|
|
159
|
+
pool.pin_connection!(lock_threads)
|
160
|
+
pool.lease_connection
|
152
161
|
end
|
153
162
|
|
154
163
|
# When connections are established in the future, begin a transaction too
|
@@ -157,59 +166,31 @@ module ActiveRecord
|
|
157
166
|
shard = payload[:shard] if payload.key?(:shard)
|
158
167
|
|
159
168
|
if connection_name
|
160
|
-
|
161
|
-
|
162
|
-
rescue ConnectionNotEstablished
|
163
|
-
connection = nil
|
164
|
-
end
|
165
|
-
|
166
|
-
if connection
|
169
|
+
pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(connection_name, shard: shard)
|
170
|
+
if pool
|
167
171
|
setup_shared_connection_pool
|
168
172
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
@
|
173
|
+
unless @fixture_connection_pools.include?(pool)
|
174
|
+
pool.pin_connection!(lock_threads)
|
175
|
+
pool.lease_connection
|
176
|
+
@fixture_connection_pools << pool
|
173
177
|
end
|
174
178
|
end
|
175
179
|
end
|
176
180
|
end
|
177
|
-
|
178
|
-
# Load fixtures for every test.
|
179
|
-
else
|
180
|
-
ActiveRecord::FixtureSet.reset_cache
|
181
|
-
@@already_loaded_fixtures[self.class] = nil
|
182
|
-
@loaded_fixtures = load_fixtures(config)
|
183
181
|
end
|
184
182
|
|
185
|
-
|
186
|
-
instantiate_fixtures if use_instantiated_fixtures
|
187
|
-
end
|
188
|
-
|
189
|
-
def teardown_fixtures
|
190
|
-
# Rollback changes if a transaction is active.
|
191
|
-
if run_in_transaction?
|
183
|
+
def teardown_transactional_fixtures
|
192
184
|
ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
|
193
|
-
@
|
194
|
-
|
195
|
-
|
185
|
+
unless @fixture_connection_pools.map(&:unpin_connection!).all?
|
186
|
+
# Something caused the transaction to be committed or rolled back
|
187
|
+
# We can no longer trust the database is in a clean state.
|
188
|
+
@@already_loaded_fixtures.clear
|
196
189
|
end
|
197
|
-
@
|
190
|
+
@fixture_connection_pools.clear
|
198
191
|
teardown_shared_connection_pool
|
199
|
-
else
|
200
|
-
ActiveRecord::FixtureSet.reset_cache
|
201
192
|
end
|
202
193
|
|
203
|
-
ActiveRecord::Base.connection_handler.clear_active_connections!(:all)
|
204
|
-
end
|
205
|
-
|
206
|
-
def enlist_fixture_connections
|
207
|
-
setup_shared_connection_pool
|
208
|
-
|
209
|
-
ActiveRecord::Base.connection_handler.connection_pool_list(:writing).map(&:connection)
|
210
|
-
end
|
211
|
-
|
212
|
-
private
|
213
194
|
# Shares the writing connection pool with connections on
|
214
195
|
# other handlers.
|
215
196
|
#
|
@@ -272,22 +253,31 @@ module ActiveRecord
|
|
272
253
|
use_instantiated_fixtures != :no_instances
|
273
254
|
end
|
274
255
|
|
275
|
-
def method_missing(
|
276
|
-
if
|
277
|
-
|
256
|
+
def method_missing(method, ...)
|
257
|
+
if fixture_sets.key?(method.name)
|
258
|
+
_active_record_fixture(method, ...)
|
278
259
|
else
|
279
260
|
super
|
280
261
|
end
|
281
262
|
end
|
282
263
|
|
283
|
-
def respond_to_missing?(
|
284
|
-
if include_private && fixture_sets.key?(name
|
264
|
+
def respond_to_missing?(method, include_private = false)
|
265
|
+
if include_private && fixture_sets.key?(method.name)
|
285
266
|
true
|
286
267
|
else
|
287
268
|
super
|
288
269
|
end
|
289
270
|
end
|
290
271
|
|
272
|
+
def _active_record_fixture(fixture_set_name, *fixture_names)
|
273
|
+
if fs_name = fixture_sets[fixture_set_name.name]
|
274
|
+
access_fixture(fs_name, *fixture_names)
|
275
|
+
else
|
276
|
+
raise StandardError, "No fixture set named '#{fixture_set_name.inspect}'"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
alias_method :fixture, :_active_record_fixture
|
280
|
+
|
291
281
|
def access_fixture(fs_name, *fixture_names)
|
292
282
|
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
293
283
|
return_single_record = fixture_names.size == 1
|