activerecord 6.1.7.4 → 7.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1449 -1014
- data/README.rdoc +3 -3
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +33 -17
- 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 +10 -3
- 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 +19 -21
- data/lib/active_record/associations/collection_proxy.rb +10 -5
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +8 -5
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +14 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +23 -15
- data/lib/active_record/associations/preloader/association.rb +186 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -14
- data/lib/active_record/associations/preloader.rb +39 -113
- data/lib/active_record/associations/singular_association.rb +15 -7
- data/lib/active_record/associations/through_association.rb +3 -3
- data/lib/active_record/associations.rb +138 -100
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -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 +49 -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 +8 -6
- data/lib/active_record/attribute_methods/serialization.rb +57 -19
- 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 +19 -22
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +17 -28
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +14 -16
- data/lib/active_record/coders/yaml_column.rb +4 -8
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -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 +47 -561
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +46 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +42 -72
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +52 -23
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +82 -25
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
- data/lib/active_record/connection_adapters/abstract_adapter.rb +153 -74
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +112 -84
- data/lib/active_record/connection_adapters/column.rb +4 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -24
- data/lib/active_record/connection_adapters/mysql/quoting.rb +45 -21
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +4 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +7 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +20 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +19 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +20 -17
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- 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 +30 -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 +71 -71
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +40 -21
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +207 -106
- data/lib/active_record/connection_adapters/schema_cache.rb +39 -38
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +25 -19
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +28 -16
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +17 -15
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +97 -32
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +49 -55
- data/lib/active_record/core.rb +123 -148
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -9
- data/lib/active_record/database_configurations/hash_config.rb +63 -5
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +15 -32
- data/lib/active_record/delegated_type.rb +53 -12
- 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 +67 -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 +206 -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 +28 -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 +90 -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 +50 -43
- data/lib/active_record/errors.rb +67 -4
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +41 -6
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +20 -23
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +5 -5
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +80 -14
- data/lib/active_record/integration.rb +4 -3
- data/lib/active_record/internal_metadata.rb +1 -5
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +36 -21
- data/lib/active_record/locking/pessimistic.rb +10 -4
- data/lib/active_record/log_subscriber.rb +23 -7
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +18 -6
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +8 -9
- data/lib/active_record/migration/compatibility.rb +91 -2
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +115 -84
- data/lib/active_record/model_schema.rb +58 -59
- data/lib/active_record/nested_attributes.rb +13 -12
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +228 -60
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +149 -0
- data/lib/active_record/querying.rb +16 -6
- data/lib/active_record/railtie.rb +136 -22
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +78 -136
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +80 -49
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +6 -6
- data/lib/active_record/relation/calculations.rb +92 -60
- data/lib/active_record/relation/delegation.rb +7 -7
- data/lib/active_record/relation/finder_methods.rb +31 -35
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +20 -1
- data/lib/active_record/relation/predicate_builder.rb +2 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +285 -68
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +189 -88
- data/lib/active_record/result.rb +23 -11
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +17 -12
- data/lib/active_record/schema.rb +38 -23
- data/lib/active_record/schema_dumper.rb +29 -19
- data/lib/active_record/schema_migration.rb +4 -4
- data/lib/active_record/scoping/default.rb +60 -13
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +64 -34
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +3 -3
- data/lib/active_record/store.rb +2 -2
- data/lib/active_record/suppressor.rb +11 -15
- data/lib/active_record/table_metadata.rb +5 -1
- data/lib/active_record/tasks/database_tasks.rb +127 -60
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -13
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +9 -6
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +3 -3
- 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 +5 -5
- 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 +4 -4
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +225 -27
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/function.rb +1 -0
- 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 +8 -3
- data/lib/arel/nodes.rb +1 -0
- data/lib/arel/predications.rb +11 -3
- 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 +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +8 -2
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +58 -2
- data/lib/arel.rb +2 -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
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +58 -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"
|
@@ -307,7 +332,7 @@ db_namespace = namespace :db do
|
|
307
332
|
|
308
333
|
desc "Retrieves the current schema version number"
|
309
334
|
task version: :load_config do
|
310
|
-
puts "Current version: #{ActiveRecord::Base.connection.
|
335
|
+
puts "Current version: #{ActiveRecord::Base.connection.schema_version}"
|
311
336
|
end
|
312
337
|
|
313
338
|
# desc "Raises an error if there are pending migrations"
|
@@ -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"
|
@@ -447,36 +452,32 @@ db_namespace = namespace :db do
|
|
447
452
|
end
|
448
453
|
|
449
454
|
namespace :schema do
|
450
|
-
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`)"
|
455
|
+
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `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
|
+
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
461
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
|
462
|
+
end
|
455
463
|
end
|
456
464
|
|
457
465
|
db_namespace["schema:dump"].reenable
|
458
466
|
end
|
459
467
|
|
460
|
-
desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the database"
|
468
|
+
desc "Loads 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"
|
461
469
|
task load: [:load_config, :check_protected_environments] do
|
462
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord
|
463
|
-
end
|
464
|
-
|
465
|
-
task load_if_ruby: ["db:create", :environment] do
|
466
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
467
|
-
Using `bin/rails db:schema:load_if_ruby` is deprecated and will be removed in Rails 7.0.
|
468
|
-
Configure the format using `config.active_record.schema_format = :ruby` to use `schema.rb` and run `bin/rails db:schema:load` instead.
|
469
|
-
MSG
|
470
|
-
db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :ruby
|
470
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
|
471
471
|
end
|
472
472
|
|
473
473
|
namespace :dump do
|
474
474
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
475
|
-
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) for #{name} database"
|
475
|
+
desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) for #{name} database"
|
476
476
|
task name => :load_config do
|
477
477
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
|
478
478
|
ActiveRecord::Base.establish_connection(db_config)
|
479
|
-
ActiveRecord
|
479
|
+
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
480
|
+
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
|
480
481
|
db_namespace["schema:dump:#{name}"].reenable
|
481
482
|
end
|
482
483
|
end
|
@@ -484,10 +485,14 @@ db_namespace = namespace :db do
|
|
484
485
|
|
485
486
|
namespace :load do
|
486
487
|
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
487
|
-
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
|
-
task name => :load_config do
|
488
|
+
desc "Loads 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"
|
489
|
+
task name => [:load_config, :check_protected_environments] do
|
490
|
+
original_db_config = ActiveRecord::Base.connection_db_config
|
489
491
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
|
490
|
-
|
492
|
+
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
493
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
|
494
|
+
ensure
|
495
|
+
ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
|
491
496
|
end
|
492
497
|
end
|
493
498
|
end
|
@@ -523,60 +528,17 @@ db_namespace = namespace :db do
|
|
523
528
|
end
|
524
529
|
end
|
525
530
|
|
526
|
-
namespace :
|
527
|
-
desc "
|
528
|
-
task
|
529
|
-
|
530
|
-
|
531
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump` instead.
|
532
|
-
MSG
|
533
|
-
|
534
|
-
db_namespace["schema:dump"].invoke
|
535
|
-
db_namespace["structure:dump"].reenable
|
536
|
-
end
|
531
|
+
namespace :encryption do
|
532
|
+
desc "Generate a set of keys for configuring Active Record encryption in a given environment"
|
533
|
+
task :init do
|
534
|
+
puts <<~MSG
|
535
|
+
Add this entry to the credentials of the target environment:#{' '}
|
537
536
|
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
|
537
|
+
active_record_encryption:
|
538
|
+
primary_key: #{SecureRandom.alphanumeric(32)}
|
539
|
+
deterministic_key: #{SecureRandom.alphanumeric(32)}
|
540
|
+
key_derivation_salt: #{SecureRandom.alphanumeric(32)}
|
543
541
|
MSG
|
544
|
-
db_namespace["schema:load"].invoke
|
545
|
-
end
|
546
|
-
|
547
|
-
task load_if_sql: ["db:create", :environment] do
|
548
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
549
|
-
Using `bin/rails db:structure:load_if_sql` is deprecated and will be removed in Rails 7.0.
|
550
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load` instead.
|
551
|
-
MSG
|
552
|
-
db_namespace["schema:load"].invoke if ActiveRecord::Base.schema_format == :sql
|
553
|
-
end
|
554
|
-
|
555
|
-
namespace :dump do
|
556
|
-
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
557
|
-
desc "Dumps the #{name} database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
|
558
|
-
task name => :load_config do
|
559
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
560
|
-
Using `bin/rails db:structure:dump:#{name}` is deprecated and will be removed in Rails 7.0.
|
561
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:dump:#{name}` instead.
|
562
|
-
MSG
|
563
|
-
db_namespace["schema:dump:#{name}"].invoke
|
564
|
-
db_namespace["structure:dump:#{name}"].reenable
|
565
|
-
end
|
566
|
-
end
|
567
|
-
end
|
568
|
-
|
569
|
-
namespace :load do
|
570
|
-
ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
|
571
|
-
desc "Recreates the #{name} database from the structure.sql file"
|
572
|
-
task name => :load_config do
|
573
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
574
|
-
Using `bin/rails db:structure:load:#{name}` is deprecated and will be removed in Rails 7.0.
|
575
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:schema:load:#{name}` instead.
|
576
|
-
MSG
|
577
|
-
db_namespace["schema:load:#{name}"].invoke
|
578
|
-
end
|
579
|
-
end
|
580
542
|
end
|
581
543
|
end
|
582
544
|
|
@@ -586,13 +548,13 @@ db_namespace = namespace :db do
|
|
586
548
|
db_namespace["test:load_schema"].invoke
|
587
549
|
end
|
588
550
|
|
589
|
-
# desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `config.active_record.schema_format`)"
|
551
|
+
# 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`)"
|
590
552
|
task load_schema: %w(db:test:purge) do
|
591
553
|
should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
|
592
554
|
ActiveRecord::Schema.verbose = false
|
593
555
|
ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
|
594
|
-
|
595
|
-
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config,
|
556
|
+
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
557
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
|
596
558
|
end
|
597
559
|
ensure
|
598
560
|
if should_reconnect
|
@@ -600,15 +562,6 @@ db_namespace = namespace :db do
|
|
600
562
|
end
|
601
563
|
end
|
602
564
|
|
603
|
-
# desc "Recreate the test database from an existent structure.sql file"
|
604
|
-
task load_structure: %w(db:test:purge) do
|
605
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
606
|
-
Using `bin/rails db:test:load_structure` is deprecated and will be removed in Rails 7.0.
|
607
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_schema` instead.
|
608
|
-
MSG
|
609
|
-
db_namespace["test:load_schema"].invoke
|
610
|
-
end
|
611
|
-
|
612
565
|
# desc "Empty the test database"
|
613
566
|
task purge: %w(load_config check_protected_environments) do
|
614
567
|
ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
|
@@ -636,9 +589,9 @@ db_namespace = namespace :db do
|
|
636
589
|
task name => "db:test:purge:#{name}" do
|
637
590
|
should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
|
638
591
|
ActiveRecord::Schema.verbose = false
|
639
|
-
filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(name)
|
640
592
|
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
|
641
|
-
|
593
|
+
schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
|
594
|
+
ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
|
642
595
|
ensure
|
643
596
|
if should_reconnect
|
644
597
|
ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
|
@@ -646,17 +599,6 @@ db_namespace = namespace :db do
|
|
646
599
|
end
|
647
600
|
end
|
648
601
|
|
649
|
-
# desc "Recreate the #{name} test database from an existent structure.sql file"
|
650
|
-
namespace :load_structure do
|
651
|
-
task name => "db:test:purge:#{name}" do
|
652
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
653
|
-
Using `bin/rails db:test:load_structure:#{name}` is deprecated and will be removed in Rails 7.0.
|
654
|
-
Configure the format using `config.active_record.schema_format = :sql` to use `structure.sql` and run `bin/rails db:test:load_structure:#{name}` instead.
|
655
|
-
MSG
|
656
|
-
db_namespace["test:load_schema:#{name}"].invoke
|
657
|
-
end
|
658
|
-
end
|
659
|
-
|
660
602
|
# desc "Empty the #{name} test database"
|
661
603
|
namespace :purge do
|
662
604
|
task name => %w(load_config check_protected_environments) do
|
@@ -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
|
@@ -10,6 +10,7 @@ module ActiveRecord
|
|
10
10
|
included do
|
11
11
|
class_attribute :_reflections, instance_writer: false, default: {}
|
12
12
|
class_attribute :aggregate_reflections, instance_writer: false, default: {}
|
13
|
+
class_attribute :automatic_scope_inversing, instance_writer: false, default: false
|
13
14
|
end
|
14
15
|
|
15
16
|
class << self
|
@@ -115,7 +116,7 @@ module ActiveRecord
|
|
115
116
|
reflections[association.to_s]
|
116
117
|
end
|
117
118
|
|
118
|
-
def _reflect_on_association(association)
|
119
|
+
def _reflect_on_association(association) # :nodoc:
|
119
120
|
_reflections[association.to_s]
|
120
121
|
end
|
121
122
|
|
@@ -194,9 +195,9 @@ module ActiveRecord
|
|
194
195
|
klass_scope
|
195
196
|
end
|
196
197
|
|
197
|
-
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
198
|
+
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
198
199
|
if scope
|
199
|
-
[scope_for(build_scope(table, predicate_builder, klass))]
|
200
|
+
[scope_for(build_scope(table, predicate_builder, klass), record)]
|
200
201
|
else
|
201
202
|
[]
|
202
203
|
end
|
@@ -234,10 +235,13 @@ module ActiveRecord
|
|
234
235
|
if has_inverse? && inverse_of.nil?
|
235
236
|
raise InverseOfAssociationNotFoundError.new(self)
|
236
237
|
end
|
238
|
+
if has_inverse? && inverse_of == self
|
239
|
+
raise InverseOfAssociationRecursiveError.new(self)
|
240
|
+
end
|
237
241
|
end
|
238
242
|
end
|
239
243
|
|
240
|
-
#
|
244
|
+
# We need to avoid the following situation:
|
241
245
|
#
|
242
246
|
# * An associated record is deleted via record.destroy
|
243
247
|
# * Hence the callbacks run, and they find a belongs_to on the record with a
|
@@ -293,6 +297,12 @@ module ActiveRecord
|
|
293
297
|
options[:strict_loading]
|
294
298
|
end
|
295
299
|
|
300
|
+
def strict_loading_violation_message(owner)
|
301
|
+
message = +"`#{owner}` is marked for strict_loading."
|
302
|
+
message << " The #{polymorphic? ? "polymorphic association" : "#{klass} association"}"
|
303
|
+
message << " named `:#{name}` cannot be lazily loaded."
|
304
|
+
end
|
305
|
+
|
296
306
|
protected
|
297
307
|
def actual_source_reflection # FIXME: this is a horrible name
|
298
308
|
self
|
@@ -306,6 +316,12 @@ module ActiveRecord
|
|
306
316
|
def primary_key(klass)
|
307
317
|
klass.primary_key || raise(UnknownPrimaryKey.new(klass))
|
308
318
|
end
|
319
|
+
|
320
|
+
def ensure_option_not_given_as_class!(option_name)
|
321
|
+
if options[option_name] && options[option_name].class == Class
|
322
|
+
raise ArgumentError, "A class was passed to `:#{option_name}` but we are expecting a string."
|
323
|
+
end
|
324
|
+
end
|
309
325
|
end
|
310
326
|
|
311
327
|
# Base class for AggregateReflection and AssociationReflection. Objects of
|
@@ -392,7 +408,7 @@ module ActiveRecord
|
|
392
408
|
|
393
409
|
# Holds all the metadata about an aggregation as it was specified in the
|
394
410
|
# Active Record class.
|
395
|
-
class AggregateReflection < MacroReflection
|
411
|
+
class AggregateReflection < MacroReflection # :nodoc:
|
396
412
|
def mapping
|
397
413
|
mapping = options[:mapping] || [name, name]
|
398
414
|
mapping.first.is_a?(Array) ? mapping : [mapping]
|
@@ -401,12 +417,29 @@ module ActiveRecord
|
|
401
417
|
|
402
418
|
# Holds all the metadata about an association as it was specified in the
|
403
419
|
# Active Record class.
|
404
|
-
class AssociationReflection < MacroReflection
|
420
|
+
class AssociationReflection < MacroReflection # :nodoc:
|
405
421
|
def compute_class(name)
|
406
422
|
if polymorphic?
|
407
423
|
raise ArgumentError, "Polymorphic associations do not support computing the class."
|
408
424
|
end
|
409
|
-
|
425
|
+
|
426
|
+
msg = <<-MSG.squish
|
427
|
+
Rails couldn't find a valid model for #{name} association.
|
428
|
+
Please provide the :class_name option on the association declaration.
|
429
|
+
If :class_name is already provided, make sure it's an ActiveRecord::Base subclass.
|
430
|
+
MSG
|
431
|
+
|
432
|
+
begin
|
433
|
+
klass = active_record.send(:compute_type, name)
|
434
|
+
|
435
|
+
unless klass < ActiveRecord::Base
|
436
|
+
raise ArgumentError, msg
|
437
|
+
end
|
438
|
+
|
439
|
+
klass
|
440
|
+
rescue NameError
|
441
|
+
raise NameError, msg
|
442
|
+
end
|
410
443
|
end
|
411
444
|
|
412
445
|
attr_reader :type, :foreign_type
|
@@ -416,11 +449,8 @@ module ActiveRecord
|
|
416
449
|
super
|
417
450
|
@type = -(options[:foreign_type]&.to_s || "#{options[:as]}_type") if options[:as]
|
418
451
|
@foreign_type = -(options[:foreign_type]&.to_s || "#{name}_type") if options[:polymorphic]
|
419
|
-
@constructable = calculate_constructable(macro, options)
|
420
452
|
|
421
|
-
|
422
|
-
raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
|
423
|
-
end
|
453
|
+
ensure_option_not_given_as_class!(:class_name)
|
424
454
|
end
|
425
455
|
|
426
456
|
def association_scope_cache(klass, owner, &block)
|
@@ -431,10 +461,6 @@ module ActiveRecord
|
|
431
461
|
klass.cached_find_by_statement(key, &block)
|
432
462
|
end
|
433
463
|
|
434
|
-
def constructable? # :nodoc:
|
435
|
-
@constructable
|
436
|
-
end
|
437
|
-
|
438
464
|
def join_table
|
439
465
|
@join_table ||= -(options[:join_table]&.to_s || derive_join_table)
|
440
466
|
end
|
@@ -459,6 +485,10 @@ module ActiveRecord
|
|
459
485
|
foreign_key
|
460
486
|
end
|
461
487
|
|
488
|
+
def join_primary_type
|
489
|
+
type
|
490
|
+
end
|
491
|
+
|
462
492
|
def join_foreign_key
|
463
493
|
active_record_primary_key
|
464
494
|
end
|
@@ -467,18 +497,17 @@ module ActiveRecord
|
|
467
497
|
check_validity_of_inverse!
|
468
498
|
end
|
469
499
|
|
470
|
-
def
|
500
|
+
def check_eager_loadable!
|
471
501
|
return unless scope
|
472
502
|
|
473
503
|
unless scope.arity == 0
|
474
504
|
raise ArgumentError, <<-MSG.squish
|
475
505
|
The association scope '#{name}' is instance dependent (the scope
|
476
|
-
block takes an argument).
|
477
|
-
not supported.
|
506
|
+
block takes an argument). Eager loading instance dependent scopes
|
507
|
+
is not supported.
|
478
508
|
MSG
|
479
509
|
end
|
480
510
|
end
|
481
|
-
alias :check_eager_loadable! :check_preloadable!
|
482
511
|
|
483
512
|
def join_id_for(owner) # :nodoc:
|
484
513
|
owner[join_foreign_key]
|
@@ -563,8 +592,9 @@ module ActiveRecord
|
|
563
592
|
options[:polymorphic]
|
564
593
|
end
|
565
594
|
|
566
|
-
|
567
|
-
|
595
|
+
def polymorphic_name
|
596
|
+
active_record.polymorphic_name
|
597
|
+
end
|
568
598
|
|
569
599
|
def add_as_source(seed)
|
570
600
|
seed
|
@@ -583,10 +613,6 @@ module ActiveRecord
|
|
583
613
|
end
|
584
614
|
|
585
615
|
private
|
586
|
-
def calculate_constructable(macro, options)
|
587
|
-
true
|
588
|
-
end
|
589
|
-
|
590
616
|
# Attempts to find the inverse association name automatically.
|
591
617
|
# If it cannot find a suitable inverse association name, it returns
|
592
618
|
# +nil+.
|
@@ -623,9 +649,10 @@ module ActiveRecord
|
|
623
649
|
# with the current reflection's klass name.
|
624
650
|
def valid_inverse_reflection?(reflection)
|
625
651
|
reflection &&
|
652
|
+
reflection != self &&
|
626
653
|
foreign_key == reflection.foreign_key &&
|
627
654
|
klass <= reflection.active_record &&
|
628
|
-
can_find_inverse_of_automatically?(reflection)
|
655
|
+
can_find_inverse_of_automatically?(reflection, true)
|
629
656
|
end
|
630
657
|
|
631
658
|
# Checks to see if the reflection doesn't have any options that prevent
|
@@ -634,14 +661,25 @@ module ActiveRecord
|
|
634
661
|
# have <tt>has_many</tt>, <tt>has_one</tt>, <tt>belongs_to</tt> associations.
|
635
662
|
# Third, we must not have options such as <tt>:foreign_key</tt>
|
636
663
|
# which prevent us from correctly guessing the inverse association.
|
637
|
-
|
638
|
-
# Anything with a scope can additionally ruin our attempt at finding an
|
639
|
-
# inverse, so we exclude reflections with scopes.
|
640
|
-
def can_find_inverse_of_automatically?(reflection)
|
664
|
+
def can_find_inverse_of_automatically?(reflection, inverse_reflection = false)
|
641
665
|
reflection.options[:inverse_of] != false &&
|
642
|
-
|
643
|
-
!
|
666
|
+
!reflection.options[:through] &&
|
667
|
+
!reflection.options[:foreign_key] &&
|
668
|
+
scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
|
669
|
+
end
|
670
|
+
|
671
|
+
# Scopes on the potential inverse reflection prevent automatic
|
672
|
+
# <tt>inverse_of</tt>, since the scope could exclude the owner record
|
673
|
+
# we would inverse from. Scopes on the reflection itself allow for
|
674
|
+
# automatic <tt>inverse_of</tt> as long as
|
675
|
+
# <tt>config.active_record.automatic_scope_inversing<tt> is set to
|
676
|
+
# +true+ (the default for new applications).
|
677
|
+
def scope_allows_automatic_inverse_of?(reflection, inverse_reflection)
|
678
|
+
if inverse_reflection
|
644
679
|
!reflection.scope
|
680
|
+
else
|
681
|
+
!reflection.scope || reflection.klass.automatic_scope_inversing
|
682
|
+
end
|
645
683
|
end
|
646
684
|
|
647
685
|
def derive_class_name
|
@@ -656,7 +694,7 @@ module ActiveRecord
|
|
656
694
|
elsif options[:as]
|
657
695
|
"#{options[:as]}_id"
|
658
696
|
else
|
659
|
-
active_record.
|
697
|
+
active_record.model_name.to_s.foreign_key
|
660
698
|
end
|
661
699
|
end
|
662
700
|
|
@@ -691,11 +729,6 @@ module ActiveRecord
|
|
691
729
|
Associations::HasOneAssociation
|
692
730
|
end
|
693
731
|
end
|
694
|
-
|
695
|
-
private
|
696
|
-
def calculate_constructable(macro, options)
|
697
|
-
!options[:through]
|
698
|
-
end
|
699
732
|
end
|
700
733
|
|
701
734
|
class BelongsToReflection < AssociationReflection # :nodoc:
|
@@ -733,13 +766,9 @@ module ActiveRecord
|
|
733
766
|
end
|
734
767
|
|
735
768
|
private
|
736
|
-
def can_find_inverse_of_automatically?(
|
769
|
+
def can_find_inverse_of_automatically?(*)
|
737
770
|
!polymorphic? && super
|
738
771
|
end
|
739
|
-
|
740
|
-
def calculate_constructable(macro, options)
|
741
|
-
!polymorphic?
|
742
|
-
end
|
743
772
|
end
|
744
773
|
|
745
774
|
class HasAndBelongsToManyReflection < AssociationReflection # :nodoc:
|
@@ -752,7 +781,7 @@ module ActiveRecord
|
|
752
781
|
|
753
782
|
# Holds all the metadata about a :through association as it was specified
|
754
783
|
# in the Active Record class.
|
755
|
-
class ThroughReflection < AbstractReflection
|
784
|
+
class ThroughReflection < AbstractReflection # :nodoc:
|
756
785
|
delegate :foreign_key, :foreign_type, :association_foreign_key, :join_id_for, :type,
|
757
786
|
:active_record_primary_key, :join_foreign_key, to: :source_reflection
|
758
787
|
|
@@ -760,6 +789,8 @@ module ActiveRecord
|
|
760
789
|
@delegate_reflection = delegate_reflection
|
761
790
|
@klass = delegate_reflection.options[:anonymous_class]
|
762
791
|
@source_reflection_name = delegate_reflection.options[:source]
|
792
|
+
|
793
|
+
ensure_option_not_given_as_class!(:source_type)
|
763
794
|
end
|
764
795
|
|
765
796
|
def through_reflection?
|
@@ -840,8 +871,8 @@ module ActiveRecord
|
|
840
871
|
source_reflection.scopes + super
|
841
872
|
end
|
842
873
|
|
843
|
-
def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
|
844
|
-
source_reflection.join_scopes(table, predicate_builder, klass) + super
|
874
|
+
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
875
|
+
source_reflection.join_scopes(table, predicate_builder, klass, record) + super
|
845
876
|
end
|
846
877
|
|
847
878
|
def has_scope?
|
@@ -1013,9 +1044,9 @@ module ActiveRecord
|
|
1013
1044
|
@previous_reflection = previous_reflection
|
1014
1045
|
end
|
1015
1046
|
|
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(
|
1047
|
+
def join_scopes(table, predicate_builder, klass = self.klass, record = nil) # :nodoc:
|
1048
|
+
scopes = @previous_reflection.join_scopes(table, predicate_builder, klass, record) + super
|
1049
|
+
scopes << build_scope(table, predicate_builder, klass).instance_exec(record, &source_type_scope)
|
1019
1050
|
end
|
1020
1051
|
|
1021
1052
|
def constraints
|