activerecord 6.1.7.6 → 7.0.8
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 +1570 -1016
- 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 +20 -22
- data/lib/active_record/associations/collection_proxy.rb +15 -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 +10 -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 +8 -2
- 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 +8 -23
- 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 +144 -82
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +115 -85
- data/lib/active_record/connection_adapters/column.rb +4 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +37 -25
- data/lib/active_record/connection_adapters/mysql/quoting.rb +50 -23
- 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 +76 -73
- 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 +33 -18
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +19 -17
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +98 -36
- 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 +93 -46
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +167 -87
- 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 +231 -61
- 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 +4 -5
- 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 +1 -6
- data/lib/active_record/relation/query_attribute.rb +28 -11
- data/lib/active_record/relation/query_methods.rb +304 -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 +6 -2
- 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 +12 -17
- 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 +9 -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/and.rb +4 -0
- 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 +55 -11
@@ -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
|