activerecord 6.1.7.10 → 7.0.0.alpha1
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.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +726 -1404
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +31 -9
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +15 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +8 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -6
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -2
- data/lib/active_record/associations/collection_association.rb +14 -23
- data/lib/active_record/associations/collection_proxy.rb +8 -3
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +161 -47
- data/lib/active_record/associations/preloader/batch.rb +51 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +37 -11
- data/lib/active_record/associations/preloader.rb +46 -110
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +76 -81
- data/lib/active_record/asynchronous_queries_tracker.rb +57 -0
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +41 -16
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +7 -5
- data/lib/active_record/attribute_methods/serialization.rb +66 -12
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +7 -10
- data/lib/active_record/attribute_methods.rb +6 -9
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +3 -18
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/coders/yaml_column.rb +2 -14
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +312 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +31 -558
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +45 -21
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +12 -14
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +60 -16
- data/lib/active_record/connection_adapters/abstract/transaction.rb +3 -3
- data/lib/active_record/connection_adapters/abstract_adapter.rb +112 -66
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +96 -81
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +33 -23
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +1 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -14
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +6 -32
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +12 -12
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +159 -102
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -37
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +23 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +4 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -30
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +20 -38
- data/lib/active_record/core.rb +111 -125
- data/lib/active_record/database_configurations/connection_url_resolver.rb +0 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -0
- data/lib/active_record/database_configurations/hash_config.rb +27 -1
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +17 -9
- data/lib/active_record/delegated_type.rb +33 -11
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +61 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +208 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +29 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +80 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +41 -41
- data/lib/active_record/errors.rb +66 -3
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +40 -5
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +16 -11
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +34 -5
- data/lib/active_record/integration.rb +1 -1
- data/lib/active_record/internal_metadata.rb +1 -5
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/log_subscriber.rb +6 -2
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +8 -3
- data/lib/active_record/migration/command_recorder.rb +4 -4
- data/lib/active_record/migration/compatibility.rb +89 -10
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +109 -79
- data/lib/active_record/model_schema.rb +45 -31
- data/lib/active_record/nested_attributes.rb +3 -3
- data/lib/active_record/no_touching.rb +2 -2
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +134 -45
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +203 -0
- data/lib/active_record/querying.rb +15 -5
- data/lib/active_record/railtie.rb +117 -17
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +72 -48
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +45 -44
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +3 -3
- data/lib/active_record/relation/calculations.rb +39 -26
- data/lib/active_record/relation/delegation.rb +6 -6
- data/lib/active_record/relation/finder_methods.rb +31 -22
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +230 -49
- data/lib/active_record/relation/record_fetch_warning.rb +2 -2
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +8 -4
- data/lib/active_record/relation.rb +166 -77
- data/lib/active_record/result.rb +17 -2
- data/lib/active_record/runtime_registry.rb +2 -4
- data/lib/active_record/sanitization.rb +11 -7
- data/lib/active_record/schema_dumper.rb +3 -3
- data/lib/active_record/schema_migration.rb +0 -4
- data/lib/active_record/scoping/default.rb +61 -12
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +40 -22
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/store.rb +1 -6
- data/lib/active_record/tasks/database_tasks.rb +106 -22
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +14 -11
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +9 -13
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +2 -2
- data/lib/active_record/type/adapter_specific_registry.rb +32 -7
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +1 -1
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record.rb +170 -2
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +18 -22
- data/lib/arel/delete_manager.rb +2 -4
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +8 -13
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/update_statement.rb +3 -2
- data/lib/arel/predications.rb +1 -1
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +0 -1
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +2 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +6 -1
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +43 -2
- data/lib/arel.rb +1 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- metadata +52 -14
@@ -86,19 +86,30 @@ db_namespace = namespace :db do
|
|
86
86
|
|
87
87
|
desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
|
88
88
|
task migrate: :load_config do
|
89
|
-
|
90
|
-
|
91
|
-
|
89
|
+
db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
|
90
|
+
|
91
|
+
if db_configs.size == 1
|
92
92
|
ActiveRecord::Tasks::DatabaseTasks.migrate
|
93
|
+
else
|
94
|
+
original_db_config = ActiveRecord::Base.connection_db_config
|
95
|
+
mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions(db_configs)
|
96
|
+
|
97
|
+
mapped_versions.sort.each do |version, db_configs|
|
98
|
+
db_configs.each do |db_config|
|
99
|
+
ActiveRecord::Base.establish_connection(db_config)
|
100
|
+
ActiveRecord::Tasks::DatabaseTasks.migrate(version)
|
101
|
+
end
|
102
|
+
end
|
93
103
|
end
|
104
|
+
|
94
105
|
db_namespace["_dump"].invoke
|
95
106
|
ensure
|
96
|
-
ActiveRecord::Base.establish_connection(original_db_config)
|
107
|
+
ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
|
97
108
|
end
|
98
109
|
|
99
|
-
# IMPORTANT: This task won't dump the schema if ActiveRecord
|
110
|
+
# IMPORTANT: This task won't dump the schema if ActiveRecord.dump_schema_after_migration is set to false
|
100
111
|
task :_dump do
|
101
|
-
if ActiveRecord
|
112
|
+
if ActiveRecord.dump_schema_after_migration
|
102
113
|
db_namespace["schema:dump"].invoke
|
103
114
|
end
|
104
115
|
# Allow this task to be called as many times as required. An example is the
|
@@ -108,11 +119,15 @@ db_namespace = namespace :db do
|
|
108
119
|
|
109
120
|
namespace :_dump do
|
110
121
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
111
|
-
# IMPORTANT: This task won't dump the schema if ActiveRecord
|
122
|
+
# IMPORTANT: This task won't dump the schema if ActiveRecord.dump_schema_after_migration is set to false
|
112
123
|
task name do
|
113
|
-
|
124
|
+
db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
|
125
|
+
|
126
|
+
if ActiveRecord.dump_schema_after_migration && db_config.schema_dump
|
127
|
+
ActiveRecord::Base.establish_connection(db_config)
|
114
128
|
db_namespace["schema:dump:#{name}"].invoke
|
115
129
|
end
|
130
|
+
|
116
131
|
# Allow this task to be called as many times as required. An example is the
|
117
132
|
# migrate:redo task, which calls other two internally that depend on this one.
|
118
133
|
db_namespace["_dump:#{name}"].reenable
|
@@ -275,6 +290,7 @@ db_namespace = namespace :db do
|
|
275
290
|
desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
|
276
291
|
task rollback: :load_config do
|
277
292
|
ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:rollback")
|
293
|
+
raise "VERSION is not supported - To rollback a specific version, use db:migrate:down" if ENV["VERSION"]
|
278
294
|
|
279
295
|
step = ENV["STEP"] ? ENV["STEP"].to_i : 1
|
280
296
|
|
@@ -290,7 +306,16 @@ db_namespace = namespace :db do
|
|
290
306
|
db_namespace["_dump"].invoke
|
291
307
|
end
|
292
308
|
|
293
|
-
|
309
|
+
namespace :reset do
|
310
|
+
task all: ["db:drop", "db:setup"]
|
311
|
+
|
312
|
+
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
313
|
+
desc "Drops and recreates the #{name} database from its schema for the current environment and loads the seeds."
|
314
|
+
task name => ["db:drop:#{name}", "db:setup:#{name}"]
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
desc "Drops and recreates all databases from their schema for the current environment and loads the seeds."
|
294
319
|
task reset: [ "db:drop", "db:setup" ]
|
295
320
|
|
296
321
|
# desc "Retrieves the charset for the current environment's database"
|
@@ -349,41 +374,21 @@ db_namespace = namespace :db do
|
|
349
374
|
end
|
350
375
|
end
|
351
376
|
|
352
|
-
|
377
|
+
namespace :setup do
|
378
|
+
task all: ["db:create", :environment, "db:schema:load", :seed]
|
379
|
+
|
380
|
+
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
381
|
+
desc "Creates the #{name} database, loads the schema, and initializes with the seed data (use db:reset:#{name} to also drop the database first)"
|
382
|
+
task name => ["db:create:#{name}", :environment, "db:schema:load:#{name}", "db:seed"]
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
desc "Creates all databases, loads all schemas, and initializes with the seed data (use db:reset to also drop all databases first)"
|
353
387
|
task setup: ["db:create", :environment, "db:schema:load", :seed]
|
354
388
|
|
355
389
|
desc "Runs setup if database does not exist, or runs migrations if it does"
|
356
390
|
task prepare: :load_config do
|
357
|
-
|
358
|
-
|
359
|
-
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
|
360
|
-
ActiveRecord::Base.establish_connection(db_config)
|
361
|
-
|
362
|
-
# Skipped when no database
|
363
|
-
ActiveRecord::Tasks::DatabaseTasks.migrate
|
364
|
-
|
365
|
-
if ActiveRecord::Base.dump_schema_after_migration
|
366
|
-
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, ActiveRecord::Base.schema_format)
|
367
|
-
end
|
368
|
-
rescue ActiveRecord::NoDatabaseError
|
369
|
-
config_name = db_config.name
|
370
|
-
ActiveRecord::Tasks::DatabaseTasks.create_current(db_config.env_name, config_name)
|
371
|
-
|
372
|
-
if File.exist?(ActiveRecord::Tasks::DatabaseTasks.dump_filename(config_name))
|
373
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(
|
374
|
-
db_config,
|
375
|
-
ActiveRecord::Base.schema_format,
|
376
|
-
nil
|
377
|
-
)
|
378
|
-
else
|
379
|
-
ActiveRecord::Tasks::DatabaseTasks.migrate
|
380
|
-
end
|
381
|
-
|
382
|
-
seed = true
|
383
|
-
end
|
384
|
-
|
385
|
-
ActiveRecord::Base.establish_connection
|
386
|
-
ActiveRecord::Tasks::DatabaseTasks.load_seed if seed
|
391
|
+
ActiveRecord::Tasks::DatabaseTasks.prepare_all
|
387
392
|
end
|
388
393
|
|
389
394
|
desc "Loads the seed data from db/seeds.rb"
|
@@ -450,8 +455,10 @@ db_namespace = namespace :db do
|
|
450
455
|
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`)"
|
451
456
|
task dump: :load_config do
|
452
457
|
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
|
453
|
-
|
454
|
-
|
458
|
+
if db_config.schema_dump
|
459
|
+
ActiveRecord::Base.establish_connection(db_config)
|
460
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
|
461
|
+
end
|
455
462
|
end
|
456
463
|
|
457
464
|
db_namespace["schema:dump"].reenable
|
@@ -459,7 +466,7 @@ db_namespace = namespace :db do
|
|
459
466
|
|
460
467
|
desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the database"
|
461
468
|
task load: [:load_config, :check_protected_environments] do
|
462
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord
|
469
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
|
463
470
|
end
|
464
471
|
|
465
472
|
task load_if_ruby: ["db:create", :environment] do
|
@@ -467,7 +474,7 @@ db_namespace = namespace :db do
|
|
467
474
|
Using `bin/rails db:schema:load_if_ruby` is deprecated and will be removed in Rails 7.0.
|
468
475
|
Configure the format using `config.active_record.schema_format = :ruby` to use `schema.rb` and run `bin/rails db:schema:load` instead.
|
469
476
|
MSG
|
470
|
-
db_namespace["schema:load"].invoke if ActiveRecord
|
477
|
+
db_namespace["schema:load"].invoke if ActiveRecord.schema_format == :ruby
|
471
478
|
end
|
472
479
|
|
473
480
|
namespace :dump do
|
@@ -486,8 +493,11 @@ db_namespace = namespace :db do
|
|
486
493
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
487
494
|
desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the #{name} database"
|
488
495
|
task name => :load_config do
|
496
|
+
original_db_config = ActiveRecord::Base.connection_db_config
|
489
497
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
|
490
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord
|
498
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord.schema_format, ENV["SCHEMA"])
|
499
|
+
ensure
|
500
|
+
ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
|
491
501
|
end
|
492
502
|
end
|
493
503
|
end
|
@@ -549,7 +559,7 @@ db_namespace = namespace :db do
|
|
549
559
|
Using `bin/rails db:structure:load_if_sql` is deprecated and will be removed in Rails 7.0.
|
550
560
|
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
|
551
561
|
MSG
|
552
|
-
db_namespace["schema:load"].invoke if ActiveRecord
|
562
|
+
db_namespace["schema:load"].invoke if ActiveRecord.schema_format == :sql
|
553
563
|
end
|
554
564
|
|
555
565
|
namespace :dump do
|
@@ -580,6 +590,20 @@ db_namespace = namespace :db do
|
|
580
590
|
end
|
581
591
|
end
|
582
592
|
|
593
|
+
namespace :encryption do
|
594
|
+
desc "Generate a set of keys for configuring Active Record encryption in a given environment"
|
595
|
+
task :init do
|
596
|
+
puts <<~MSG
|
597
|
+
Add this entry to the credentials of the target environment:#{' '}
|
598
|
+
|
599
|
+
active_record_encryption:
|
600
|
+
primary_key: #{SecureRandom.alphanumeric(32)}
|
601
|
+
deterministic_key: #{SecureRandom.alphanumeric(32)}
|
602
|
+
key_derivation_salt: #{SecureRandom.alphanumeric(32)}
|
603
|
+
MSG
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
583
607
|
namespace :test do
|
584
608
|
# desc "Recreate the test database from the current schema"
|
585
609
|
task load: %w(db:test:purge) do
|
@@ -592,7 +616,7 @@ db_namespace = namespace :db do
|
|
592
616
|
ActiveRecord::Schema.verbose = false
|
593
617
|
ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
|
594
618
|
filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.name)
|
595
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord
|
619
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord.schema_format, filename)
|
596
620
|
end
|
597
621
|
ensure
|
598
622
|
if should_reconnect
|
@@ -638,7 +662,7 @@ db_namespace = namespace :db do
|
|
638
662
|
ActiveRecord::Schema.verbose = false
|
639
663
|
filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(name)
|
640
664
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
|
641
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord
|
665
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, ActiveRecord.schema_format, filename)
|
642
666
|
ensure
|
643
667
|
if should_reconnect
|
644
668
|
ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
|
@@ -11,6 +11,17 @@ module ActiveRecord
|
|
11
11
|
module ClassMethods
|
12
12
|
# Attributes listed as readonly will be used to create a new record but update operations will
|
13
13
|
# ignore these fields.
|
14
|
+
#
|
15
|
+
# You can assign a new value to a readonly attribute, but it will be ignored when the record is updated.
|
16
|
+
#
|
17
|
+
# ==== Examples
|
18
|
+
#
|
19
|
+
# class Post < ActiveRecord::Base
|
20
|
+
# attr_readonly :title
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# post = Post.create!(title: "Introducing Ruby on Rails!")
|
24
|
+
# post.update(title: "a different title") # change to title will be ignored
|
14
25
|
def attr_readonly(*attributes)
|
15
26
|
self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
|
16
27
|
end
|
@@ -115,7 +115,7 @@ module ActiveRecord
|
|
115
115
|
reflections[association.to_s]
|
116
116
|
end
|
117
117
|
|
118
|
-
def _reflect_on_association(association)
|
118
|
+
def _reflect_on_association(association) # :nodoc:
|
119
119
|
_reflections[association.to_s]
|
120
120
|
end
|
121
121
|
|
@@ -194,9 +194,9 @@ module ActiveRecord
|
|
194
194
|
klass_scope
|
195
195
|
end
|
196
196
|
|
197
|
-
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
197
|
+
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
198
198
|
if scope
|
199
|
-
[scope_for(build_scope(table, predicate_builder, klass))]
|
199
|
+
[scope_for(build_scope(table, predicate_builder, klass), record)]
|
200
200
|
else
|
201
201
|
[]
|
202
202
|
end
|
@@ -237,7 +237,7 @@ module ActiveRecord
|
|
237
237
|
end
|
238
238
|
end
|
239
239
|
|
240
|
-
#
|
240
|
+
# We need to avoid the following situation:
|
241
241
|
#
|
242
242
|
# * An associated record is deleted via record.destroy
|
243
243
|
# * Hence the callbacks run, and they find a belongs_to on the record with a
|
@@ -306,6 +306,12 @@ module ActiveRecord
|
|
306
306
|
def primary_key(klass)
|
307
307
|
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
308
308
|
end
|
309
|
+
|
310
|
+
def ensure_option_not_given_as_class!(option_name)
|
311
|
+
if options[option_name] && options[option_name].class == Class
|
312
|
+
raise ArgumentError, "A class was passed to `:#{option_name}` but we are expecting a string."
|
313
|
+
end
|
314
|
+
end
|
309
315
|
end
|
310
316
|
|
311
317
|
# Base class for AggregateReflection and AssociationReflection. Objects of
|
@@ -392,7 +398,7 @@ module ActiveRecord
|
|
392
398
|
|
393
399
|
# Holds all the metadata about an aggregation as it was specified in the
|
394
400
|
# Active Record class.
|
395
|
-
class AggregateReflection < MacroReflection
|
401
|
+
class AggregateReflection < MacroReflection # :nodoc:
|
396
402
|
def mapping
|
397
403
|
mapping = options[:mapping] || [name, name]
|
398
404
|
mapping.first.is_a?(Array) ? mapping : [mapping]
|
@@ -401,12 +407,29 @@ module ActiveRecord
|
|
401
407
|
|
402
408
|
# Holds all the metadata about an association as it was specified in the
|
403
409
|
# Active Record class.
|
404
|
-
class AssociationReflection < MacroReflection
|
410
|
+
class AssociationReflection < MacroReflection # :nodoc:
|
405
411
|
def compute_class(name)
|
406
412
|
if polymorphic?
|
407
413
|
raise ArgumentError, "Polymorphic associations do not support computing the class."
|
408
414
|
end
|
409
|
-
|
415
|
+
|
416
|
+
msg = <<-MSG.squish
|
417
|
+
Rails couldn't find a valid model for #{name} association.
|
418
|
+
Please provide the :class_name option on the association declaration.
|
419
|
+
If :class_name is already provided, make sure it's an ActiveRecord::Base subclass.
|
420
|
+
MSG
|
421
|
+
|
422
|
+
begin
|
423
|
+
klass = active_record.send(:compute_type, name)
|
424
|
+
|
425
|
+
unless klass < ActiveRecord::Base
|
426
|
+
raise ArgumentError, msg
|
427
|
+
end
|
428
|
+
|
429
|
+
klass
|
430
|
+
rescue NameError
|
431
|
+
raise NameError, msg
|
432
|
+
end
|
410
433
|
end
|
411
434
|
|
412
435
|
attr_reader :type, :foreign_type
|
@@ -416,11 +439,8 @@ module ActiveRecord
|
|
416
439
|
super
|
417
440
|
@type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
|
418
441
|
@foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]
|
419
|
-
@constructable = calculate_constructable(macro, options)
|
420
442
|
|
421
|
-
|
422
|
-
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
423
|
-
end
|
443
|
+
ensure_option_not_given_as_class!(:class_name)
|
424
444
|
end
|
425
445
|
|
426
446
|
def association_scope_cache(klass, owner, &block)
|
@@ -431,10 +451,6 @@ module ActiveRecord
|
|
431
451
|
klass.cached_find_by_statement(key, &block)
|
432
452
|
end
|
433
453
|
|
434
|
-
def constructable? # :nodoc:
|
435
|
-
@constructable
|
436
|
-
end
|
437
|
-
|
438
454
|
def join_table
|
439
455
|
@join_table ||= -(options[:join_table]&.to_s || derive_join_table)
|
440
456
|
end
|
@@ -467,18 +483,17 @@ module ActiveRecord
|
|
467
483
|
check_validity_of_inverse!
|
468
484
|
end
|
469
485
|
|
470
|
-
def
|
486
|
+
def check_eager_loadable!
|
471
487
|
return unless scope
|
472
488
|
|
473
489
|
unless scope.arity == 0
|
474
490
|
raise ArgumentError, <<-MSG.squish
|
475
491
|
The association scope '#{name}' is instance dependent (the scope
|
476
|
-
block takes an argument).
|
477
|
-
not supported.
|
492
|
+
block takes an argument). Eager loading instance dependent scopes
|
493
|
+
is not supported.
|
478
494
|
MSG
|
479
495
|
end
|
480
496
|
end
|
481
|
-
alias :check_eager_loadable! :check_preloadable!
|
482
497
|
|
483
498
|
def join_id_for(owner) # :nodoc:
|
484
499
|
owner[join_foreign_key]
|
@@ -563,9 +578,6 @@ module ActiveRecord
|
|
563
578
|
options[:polymorphic]
|
564
579
|
end
|
565
580
|
|
566
|
-
VALID_AUTOMATIC_INVERSE_MACROS = [:has_many, :has_one, :belongs_to]
|
567
|
-
INVALID_AUTOMATIC_INVERSE_OPTIONS = [:through, :foreign_key]
|
568
|
-
|
569
581
|
def add_as_source(seed)
|
570
582
|
seed
|
571
583
|
end
|
@@ -583,10 +595,6 @@ module ActiveRecord
|
|
583
595
|
end
|
584
596
|
|
585
597
|
private
|
586
|
-
def calculate_constructable(macro, options)
|
587
|
-
true
|
588
|
-
end
|
589
|
-
|
590
598
|
# Attempts to find the inverse association name automatically.
|
591
599
|
# If it cannot find a suitable inverse association name, it returns
|
592
600
|
# +nil+.
|
@@ -639,8 +647,8 @@ module ActiveRecord
|
|
639
647
|
# inverse, so we exclude reflections with scopes.
|
640
648
|
def can_find_inverse_of_automatically?(reflection)
|
641
649
|
reflection.options[:inverse_of] != false &&
|
642
|
-
|
643
|
-
!
|
650
|
+
!reflection.options[:through] &&
|
651
|
+
!reflection.options[:foreign_key] &&
|
644
652
|
!reflection.scope
|
645
653
|
end
|
646
654
|
|
@@ -656,7 +664,7 @@ module ActiveRecord
|
|
656
664
|
elsif options[:as]
|
657
665
|
"#{options[:as]}_id"
|
658
666
|
else
|
659
|
-
active_record.
|
667
|
+
active_record.model_name.to_s.foreign_key
|
660
668
|
end
|
661
669
|
end
|
662
670
|
|
@@ -691,11 +699,6 @@ module ActiveRecord
|
|
691
699
|
Associations::HasOneAssociation
|
692
700
|
end
|
693
701
|
end
|
694
|
-
|
695
|
-
private
|
696
|
-
def calculate_constructable(macro, options)
|
697
|
-
!options[:through]
|
698
|
-
end
|
699
702
|
end
|
700
703
|
|
701
704
|
class BelongsToReflection < AssociationReflection # :nodoc:
|
@@ -736,10 +739,6 @@ module ActiveRecord
|
|
736
739
|
def can_find_inverse_of_automatically?(_)
|
737
740
|
!polymorphic? && super
|
738
741
|
end
|
739
|
-
|
740
|
-
def calculate_constructable(macro, options)
|
741
|
-
!polymorphic?
|
742
|
-
end
|
743
742
|
end
|
744
743
|
|
745
744
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
@@ -752,7 +751,7 @@ module ActiveRecord
|
|
752
751
|
|
753
752
|
# Holds all the metadata about a :through association as it was specified
|
754
753
|
# in the Active Record class.
|
755
|
-
class ThroughReflection < AbstractReflection
|
754
|
+
class ThroughReflection < AbstractReflection # :nodoc:
|
756
755
|
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type,
|
757
756
|
:active_record_primary_key, :join_foreign_key, to: :source_reflection
|
758
757
|
|
@@ -760,6 +759,8 @@ module ActiveRecord
|
|
760
759
|
@delegate_reflection = delegate_reflection
|
761
760
|
@klass = delegate_reflection.options[:anonymous_class]
|
762
761
|
@source_reflection_name = delegate_reflection.options[:source]
|
762
|
+
|
763
|
+
ensure_option_not_given_as_class!(:source_type)
|
763
764
|
end
|
764
765
|
|
765
766
|
def through_reflection?
|
@@ -840,8 +841,8 @@ module ActiveRecord
|
|
840
841
|
source_reflection.scopes + super
|
841
842
|
end
|
842
843
|
|
843
|
-
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
844
|
-
source_reflection.join_scopes(table, predicate_builder, klass) + super
|
844
|
+
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
845
|
+
source_reflection.join_scopes(table, predicate_builder, klass, record) + super
|
845
846
|
end
|
846
847
|
|
847
848
|
def has_scope?
|
@@ -1013,9 +1014,9 @@ module ActiveRecord
|
|
1013
1014
|
@previous_reflection = previous_reflection
|
1014
1015
|
end
|
1015
1016
|
|
1016
|
-
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
1017
|
-
scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
|
1018
|
-
scopes << build_scope(table, predicate_builder, klass).instance_exec(
|
1017
|
+
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
1018
|
+
scopes = @previous_reflection.join_scopes(table, predicate_builder, record) + super
|
1019
|
+
scopes << build_scope(table, predicate_builder, klass).instance_exec(record, &source_type_scope)
|
1019
1020
|
end
|
1020
1021
|
|
1021
1022
|
def constraints
|
@@ -5,13 +5,27 @@ module ActiveRecord
|
|
5
5
|
class BatchEnumerator
|
6
6
|
include Enumerable
|
7
7
|
|
8
|
-
def initialize(of: 1000, start: nil, finish: nil, relation:)
|
8
|
+
def initialize(of: 1000, start: nil, finish: nil, relation:) # :nodoc:
|
9
9
|
@of = of
|
10
10
|
@relation = relation
|
11
11
|
@start = start
|
12
12
|
@finish = finish
|
13
13
|
end
|
14
14
|
|
15
|
+
# The primary key value from which the BatchEnumerator starts, inclusive of the value.
|
16
|
+
attr_reader :start
|
17
|
+
|
18
|
+
# The primary key value at which the BatchEnumerator ends, inclusive of the value.
|
19
|
+
attr_reader :finish
|
20
|
+
|
21
|
+
# The relation from which the BatchEnumerator yields batches.
|
22
|
+
attr_reader :relation
|
23
|
+
|
24
|
+
# The size of the batches yielded by the BatchEnumerator.
|
25
|
+
def batch_size
|
26
|
+
@of
|
27
|
+
end
|
28
|
+
|
15
29
|
# Looping through a collection of records from the database (using the
|
16
30
|
# +all+ method, for example) is very inefficient since it will try to
|
17
31
|
# instantiate all the objects at once.
|
@@ -33,11 +47,11 @@ module ActiveRecord
|
|
33
47
|
# Person.in_batches.each_record.with_index do |person, index|
|
34
48
|
# person.award_trophy(index + 1)
|
35
49
|
# end
|
36
|
-
def each_record
|
50
|
+
def each_record(&block)
|
37
51
|
return to_enum(:each_record) unless block_given?
|
38
52
|
|
39
53
|
@relation.to_enum(:in_batches, of: @of, start: @start, finish: @finish, load: true).each do |relation|
|
40
|
-
relation.records.each
|
54
|
+
relation.records.each(&block)
|
41
55
|
end
|
42
56
|
end
|
43
57
|
|
@@ -75,9 +89,9 @@ module ActiveRecord
|
|
75
89
|
# Person.in_batches.each do |relation|
|
76
90
|
# relation.update_all(awesome: true)
|
77
91
|
# end
|
78
|
-
def each
|
92
|
+
def each(&block)
|
79
93
|
enum = @relation.to_enum(:in_batches, of: @of, start: @start, finish: @finish, load: false)
|
80
|
-
return enum.each
|
94
|
+
return enum.each(&block) if block_given?
|
81
95
|
enum
|
82
96
|
end
|
83
97
|
end
|
@@ -65,10 +65,10 @@ module ActiveRecord
|
|
65
65
|
#
|
66
66
|
# NOTE: By its nature, batch processing is subject to race conditions if
|
67
67
|
# other processes are modifying the database.
|
68
|
-
def find_each(start: nil, finish: nil, batch_size: 1000, error_on_ignore: nil, order: :asc)
|
68
|
+
def find_each(start: nil, finish: nil, batch_size: 1000, error_on_ignore: nil, order: :asc, &block)
|
69
69
|
if block_given?
|
70
70
|
find_in_batches(start: start, finish: finish, batch_size: batch_size, error_on_ignore: error_on_ignore, order: order) do |records|
|
71
|
-
records.each
|
71
|
+
records.each(&block)
|
72
72
|
end
|
73
73
|
else
|
74
74
|
enum_for(:find_each, start: start, finish: finish, batch_size: batch_size, error_on_ignore: error_on_ignore, order: order) do
|
@@ -284,7 +284,7 @@ module ActiveRecord
|
|
284
284
|
end
|
285
285
|
|
286
286
|
def act_on_ignored_order(error_on_ignore)
|
287
|
-
raise_error = (error_on_ignore.nil? ?
|
287
|
+
raise_error = (error_on_ignore.nil? ? ActiveRecord.error_on_ignored_order : error_on_ignore)
|
288
288
|
|
289
289
|
if raise_error
|
290
290
|
raise ArgumentError.new(ORDER_IGNORE_MESSAGE)
|