activerecord 6.1.7 → 7.1.0
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 +1516 -1019
- data/MIT-LICENSE +1 -1
- data/README.rdoc +17 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +50 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- 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 +6 -2
- data/lib/active_record/associations/collection_association.rb +35 -31
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +26 -16
- data/lib/active_record/associations/preloader/association.rb +207 -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 +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +423 -289
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +61 -14
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +25 -10
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +10 -13
- data/lib/active_record/attribute_methods.rb +121 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +61 -30
- data/lib/active_record/base.rb +25 -2
- data/lib/active_record/callbacks.rb +18 -34
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +96 -590
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +171 -51
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +77 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +360 -136
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +622 -149
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +285 -156
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +104 -53
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +18 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +86 -52
- 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 +12 -3
- 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 +89 -56
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +381 -69
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +492 -230
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +65 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +294 -102
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +107 -136
- data/lib/active_record/core.rb +194 -224
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +84 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +61 -15
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -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/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +224 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +151 -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 +172 -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 +53 -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 +92 -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 +96 -0
- data/lib/active_record/encryption.rb +56 -0
- data/lib/active_record/enum.rb +156 -62
- data/lib/active_record/errors.rb +171 -15
- data/lib/active_record/explain.rb +23 -3
- 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/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +131 -86
- data/lib/active_record/future_result.rb +164 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +133 -20
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +117 -33
- 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 +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +108 -13
- data/lib/active_record/migration/compatibility.rb +221 -48
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +355 -171
- data/lib/active_record/model_schema.rb +116 -97
- data/lib/active_record/nested_attributes.rb +36 -15
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +159 -0
- data/lib/active_record/persistence.rb +405 -85
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +219 -43
- data/lib/active_record/railties/controller_runtime.rb +13 -9
- data/lib/active_record/railties/databases.rake +185 -249
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +229 -80
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +211 -90
- data/lib/active_record/relation/delegation.rb +27 -13
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +654 -127
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +262 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +18 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +10 -8
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +225 -136
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +116 -96
- data/lib/active_record/timestamp.rb +28 -17
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -5
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- 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/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- 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/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +0 -8
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- 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 +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +139 -19
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- 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 +92 -13
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= Active Record -- Object-relational mapping in Rails
|
1
|
+
= Active Record -- Object-relational mapping in \Rails
|
2
2
|
|
3
3
|
Active Record connects classes to relational database tables to establish an
|
4
4
|
almost zero-configuration persistence layer for applications. The library
|
@@ -13,29 +13,28 @@ columns. Although these mappings can be defined explicitly, it's recommended
|
|
13
13
|
to follow naming conventions, especially when getting started with the
|
14
14
|
library.
|
15
15
|
|
16
|
-
You can read more about Active Record in the {Active Record Basics}[https://
|
16
|
+
You can read more about Active Record in the {Active Record Basics}[https://guides.rubyonrails.org/active_record_basics.html] guide.
|
17
17
|
|
18
18
|
A short rundown of some of the major features:
|
19
19
|
|
20
20
|
* Automated mapping between classes and tables, attributes and columns.
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
{Learn more}[link:classes/ActiveRecord/Base.html]
|
22
|
+
class Product < ActiveRecord::Base
|
23
|
+
end
|
26
24
|
|
27
|
-
The Product class is automatically mapped to the table named "products",
|
28
|
-
which might look like this:
|
25
|
+
The Product class is automatically mapped to the table named "products",
|
26
|
+
which might look like this:
|
29
27
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
CREATE TABLE products (
|
29
|
+
id bigint NOT NULL auto_increment,
|
30
|
+
name varchar(255),
|
31
|
+
PRIMARY KEY (id)
|
32
|
+
);
|
35
33
|
|
36
|
-
This would also define the following accessors: <tt>Product#name</tt> and
|
37
|
-
<tt>Product#name=(new_name)</tt>.
|
34
|
+
This would also define the following accessors: <tt>Product#name</tt> and
|
35
|
+
<tt>Product#name=(new_name)</tt>.
|
38
36
|
|
37
|
+
{Learn more}[link:classes/ActiveRecord/Base.html]
|
39
38
|
|
40
39
|
* Associations between objects defined by simple class methods.
|
41
40
|
|
@@ -140,7 +139,7 @@ This would also define the following accessors: <tt>Product#name</tt> and
|
|
140
139
|
|
141
140
|
* Database agnostic schema management with Migrations.
|
142
141
|
|
143
|
-
class AddSystemSettings < ActiveRecord::Migration[
|
142
|
+
class AddSystemSettings < ActiveRecord::Migration[7.1]
|
144
143
|
def up
|
145
144
|
create_table :system_settings do |t|
|
146
145
|
t.string :name
|
@@ -192,7 +191,7 @@ The latest version of Active Record can be installed with RubyGems:
|
|
192
191
|
|
193
192
|
$ gem install activerecord
|
194
193
|
|
195
|
-
Source code can be downloaded as part of the Rails project on GitHub:
|
194
|
+
Source code can be downloaded as part of the \Rails project on GitHub:
|
196
195
|
|
197
196
|
* https://github.com/rails/rails/tree/main/activerecord
|
198
197
|
|
@@ -210,7 +209,7 @@ API documentation is at:
|
|
210
209
|
|
211
210
|
* https://api.rubyonrails.org
|
212
211
|
|
213
|
-
Bug reports for the Ruby on Rails project can be filed here:
|
212
|
+
Bug reports for the Ruby on \Rails project can be filed here:
|
214
213
|
|
215
214
|
* https://github.com/rails/rails/issues
|
216
215
|
|
@@ -4,7 +4,7 @@ module ActiveRecord
|
|
4
4
|
# See ActiveRecord::Aggregations::ClassMethods for documentation
|
5
5
|
module Aggregations
|
6
6
|
def initialize_dup(*) # :nodoc:
|
7
|
-
@aggregation_cache =
|
7
|
+
@aggregation_cache = @aggregation_cache.dup
|
8
8
|
super
|
9
9
|
end
|
10
10
|
|
@@ -19,10 +19,12 @@ module ActiveRecord
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def init_internals
|
22
|
-
@aggregation_cache = {}
|
23
22
|
super
|
23
|
+
@aggregation_cache = {}
|
24
24
|
end
|
25
25
|
|
26
|
+
# = Active Record \Aggregations
|
27
|
+
#
|
26
28
|
# Active Record implements aggregation through a macro-like class method called #composed_of
|
27
29
|
# for representing attributes as value objects. It expresses relationships like "Account [is]
|
28
30
|
# composed of Money [among other things]" or "Person [is] composed of [an] address". Each call
|
@@ -32,8 +34,8 @@ module ActiveRecord
|
|
32
34
|
# the database).
|
33
35
|
#
|
34
36
|
# class Customer < ActiveRecord::Base
|
35
|
-
# composed_of :balance, class_name: "Money", mapping:
|
36
|
-
# composed_of :address, mapping:
|
37
|
+
# composed_of :balance, class_name: "Money", mapping: { balance: :amount }
|
38
|
+
# composed_of :address, mapping: { address_street: :street, address_city: :city }
|
37
39
|
# end
|
38
40
|
#
|
39
41
|
# The customer class now has the following methods to manipulate the value objects:
|
@@ -150,7 +152,7 @@ module ActiveRecord
|
|
150
152
|
# class NetworkResource < ActiveRecord::Base
|
151
153
|
# composed_of :cidr,
|
152
154
|
# class_name: 'NetAddr::CIDR',
|
153
|
-
# mapping:
|
155
|
+
# mapping: { network_address: :network, cidr_range: :bits },
|
154
156
|
# allow_nil: true,
|
155
157
|
# constructor: Proc.new { |network_address, cidr_range| NetAddr::CIDR.create("#{network_address}/#{cidr_range}") },
|
156
158
|
# converter: Proc.new { |value| NetAddr::CIDR.create(value.is_a?(Array) ? value.join('/') : value) }
|
@@ -188,10 +190,10 @@ module ActiveRecord
|
|
188
190
|
# to the Address class, but if the real class name is +CompanyAddress+, you'll have to specify it
|
189
191
|
# with this option.
|
190
192
|
# * <tt>:mapping</tt> - Specifies the mapping of entity attributes to attributes of the value
|
191
|
-
# object. Each mapping is represented as
|
192
|
-
# entity attribute and the
|
193
|
+
# object. Each mapping is represented as a key-value pair where the key is the name of the
|
194
|
+
# entity attribute and the value is the name of the attribute in the value object. The
|
193
195
|
# order in which mappings are defined determines the order in which attributes are sent to the
|
194
|
-
# value class constructor.
|
196
|
+
# value class constructor. The mapping can be written as a hash or as an array of pairs.
|
195
197
|
# * <tt>:allow_nil</tt> - Specifies that the value object will not be instantiated when all mapped
|
196
198
|
# attributes are +nil+. Setting the value object to +nil+ has the effect of writing +nil+ to all
|
197
199
|
# mapped attributes.
|
@@ -208,14 +210,15 @@ module ActiveRecord
|
|
208
210
|
# can return +nil+ to skip the assignment.
|
209
211
|
#
|
210
212
|
# Option examples:
|
211
|
-
# composed_of :temperature, mapping:
|
212
|
-
# composed_of :balance, class_name: "Money", mapping:
|
213
|
+
# composed_of :temperature, mapping: { reading: :celsius }
|
214
|
+
# composed_of :balance, class_name: "Money", mapping: { balance: :amount }
|
215
|
+
# composed_of :address, mapping: { address_street: :street, address_city: :city }
|
213
216
|
# composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
|
214
217
|
# composed_of :gps_location
|
215
218
|
# composed_of :gps_location, allow_nil: true
|
216
219
|
# composed_of :ip_address,
|
217
220
|
# class_name: 'IPAddr',
|
218
|
-
# mapping:
|
221
|
+
# mapping: { ip: :to_i },
|
219
222
|
# constructor: Proc.new { |ip| IPAddr.new(ip, Socket::AF_INET) },
|
220
223
|
# converter: Proc.new { |ip| ip.is_a?(Integer) ? IPAddr.new(ip, Socket::AF_INET) : IPAddr.new(ip.to_s) }
|
221
224
|
#
|
@@ -249,7 +252,7 @@ module ActiveRecord
|
|
249
252
|
object = constructor.respond_to?(:call) ?
|
250
253
|
constructor.call(*attrs) :
|
251
254
|
class_name.constantize.send(constructor, *attrs)
|
252
|
-
@aggregation_cache[name] = object
|
255
|
+
@aggregation_cache[name] = object.freeze
|
253
256
|
end
|
254
257
|
@aggregation_cache[name]
|
255
258
|
end
|
@@ -264,7 +267,7 @@ module ActiveRecord
|
|
264
267
|
end
|
265
268
|
|
266
269
|
hash_from_multiparameter_assignment = part.is_a?(Hash) &&
|
267
|
-
part.
|
270
|
+
part.keys.all?(Integer)
|
268
271
|
if hash_from_multiparameter_assignment
|
269
272
|
raise ArgumentError unless part.size == part.each_key.max
|
270
273
|
part = klass.new(*part.sort.map(&:last))
|
@@ -275,7 +278,7 @@ module ActiveRecord
|
|
275
278
|
@aggregation_cache[name] = nil
|
276
279
|
else
|
277
280
|
mapping.each { |key, value| write_attribute(key, part.send(value)) }
|
278
|
-
@aggregation_cache[name] = part.freeze
|
281
|
+
@aggregation_cache[name] = part.dup.freeze
|
279
282
|
end
|
280
283
|
end
|
281
284
|
end
|
@@ -16,7 +16,7 @@ module ActiveRecord
|
|
16
16
|
end
|
17
17
|
|
18
18
|
%w(insert insert_all insert! insert_all! upsert upsert_all).each do |method|
|
19
|
-
class_eval <<~RUBY
|
19
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
20
20
|
def #{method}(attributes, **kwargs)
|
21
21
|
if @association.reflection.through_reflection?
|
22
22
|
raise ArgumentError, "Bulk insert or upsert is currently not supported for has_many through association"
|
@@ -27,16 +27,6 @@ module ActiveRecord
|
|
27
27
|
RUBY
|
28
28
|
end
|
29
29
|
|
30
|
-
def build(attributes = nil, &block)
|
31
|
-
if attributes.is_a?(Array)
|
32
|
-
attributes.collect { |attr| build(attr, &block) }
|
33
|
-
else
|
34
|
-
block = current_scope_restoring_block(&block)
|
35
|
-
scoping { _new(attributes, &block) }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
alias new build
|
39
|
-
|
40
30
|
private
|
41
31
|
def _new(attributes, &block)
|
42
32
|
@association.build(attributes, &block)
|
@@ -19,7 +19,7 @@ module ActiveRecord
|
|
19
19
|
# Associations in Active Record are middlemen between the object that
|
20
20
|
# holds the association, known as the <tt>owner</tt>, and the associated
|
21
21
|
# result set, known as the <tt>target</tt>. Association metadata is available in
|
22
|
-
# <tt>reflection</tt>, which is an instance of
|
22
|
+
# <tt>reflection</tt>, which is an instance of +ActiveRecord::Reflection::AssociationReflection+.
|
23
23
|
#
|
24
24
|
# For example, given
|
25
25
|
#
|
@@ -32,8 +32,8 @@ module ActiveRecord
|
|
32
32
|
# The association of <tt>blog.posts</tt> has the object +blog+ as its
|
33
33
|
# <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
|
34
34
|
# the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
|
35
|
-
class Association
|
36
|
-
attr_reader :owner, :target, :reflection
|
35
|
+
class Association # :nodoc:
|
36
|
+
attr_reader :owner, :target, :reflection, :disable_joins
|
37
37
|
|
38
38
|
delegate :options, to: :reflection
|
39
39
|
|
@@ -41,9 +41,12 @@ module ActiveRecord
|
|
41
41
|
reflection.check_validity!
|
42
42
|
|
43
43
|
@owner, @reflection = owner, reflection
|
44
|
+
@disable_joins = @reflection.options[:disable_joins] || false
|
44
45
|
|
45
46
|
reset
|
46
47
|
reset_scope
|
48
|
+
|
49
|
+
@skip_strict_loading = nil
|
47
50
|
end
|
48
51
|
|
49
52
|
# Resets the \loaded flag to +false+ and sets the \target to +nil+.
|
@@ -51,7 +54,6 @@ module ActiveRecord
|
|
51
54
|
@loaded = false
|
52
55
|
@target = nil
|
53
56
|
@stale_state = nil
|
54
|
-
@inversed = false
|
55
57
|
end
|
56
58
|
|
57
59
|
def reset_negative_cache # :nodoc:
|
@@ -77,7 +79,6 @@ module ActiveRecord
|
|
77
79
|
def loaded!
|
78
80
|
@loaded = true
|
79
81
|
@stale_state = stale_state
|
80
|
-
@inversed = false
|
81
82
|
end
|
82
83
|
|
83
84
|
# The target is stale if the target no longer points to the record(s) that the
|
@@ -87,7 +88,7 @@ module ActiveRecord
|
|
87
88
|
#
|
88
89
|
# Note that if the target has not been loaded, it is not considered stale.
|
89
90
|
def stale_target?
|
90
|
-
|
91
|
+
loaded? && @stale_state != stale_state
|
91
92
|
end
|
92
93
|
|
93
94
|
# Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
|
@@ -97,8 +98,12 @@ module ActiveRecord
|
|
97
98
|
end
|
98
99
|
|
99
100
|
def scope
|
100
|
-
if
|
101
|
+
if disable_joins
|
102
|
+
DisableJoinsAssociationScope.create.scope(self)
|
103
|
+
elsif (scope = klass.current_scope) && scope.try(:proxy_association) == self
|
101
104
|
scope.spawn
|
105
|
+
elsif scope = klass.global_current_scope
|
106
|
+
target_scope.merge!(association_scope).merge!(scope)
|
102
107
|
else
|
103
108
|
target_scope.merge!(association_scope)
|
104
109
|
end
|
@@ -132,15 +137,11 @@ module ActiveRecord
|
|
132
137
|
|
133
138
|
def inversed_from(record)
|
134
139
|
self.target = record
|
135
|
-
@inversed = !!record
|
136
140
|
end
|
137
141
|
|
138
142
|
def inversed_from_queries(record)
|
139
143
|
if inversable?(record)
|
140
144
|
self.target = record
|
141
|
-
@inversed = true
|
142
|
-
else
|
143
|
-
@inversed = false
|
144
145
|
end
|
145
146
|
end
|
146
147
|
|
@@ -191,7 +192,7 @@ module ActiveRecord
|
|
191
192
|
@reflection = @owner.class._reflect_on_association(reflection_name)
|
192
193
|
end
|
193
194
|
|
194
|
-
def initialize_attributes(record, except_from_scope_attributes = nil)
|
195
|
+
def initialize_attributes(record, except_from_scope_attributes = nil) # :nodoc:
|
195
196
|
except_from_scope_attributes ||= {}
|
196
197
|
skip_assign = [reflection.foreign_key, reflection.type].compact
|
197
198
|
assigned_keys = record.changed_attribute_names_to_save
|
@@ -210,8 +211,14 @@ module ActiveRecord
|
|
210
211
|
end
|
211
212
|
|
212
213
|
private
|
214
|
+
# Reader and writer methods call this so that consistent errors are presented
|
215
|
+
# when the association target class does not exist.
|
216
|
+
def ensure_klass_exists!
|
217
|
+
klass
|
218
|
+
end
|
219
|
+
|
213
220
|
def find_target
|
214
|
-
if
|
221
|
+
if violates_strict_loading?
|
215
222
|
Base.strict_loading_violation!(owner: owner.class, reflection: reflection)
|
216
223
|
end
|
217
224
|
|
@@ -224,13 +231,32 @@ module ActiveRecord
|
|
224
231
|
end
|
225
232
|
|
226
233
|
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
227
|
-
sc.execute(binds, klass.connection)
|
234
|
+
sc.execute(binds, klass.connection) do |record|
|
235
|
+
set_inverse_instance(record)
|
236
|
+
if owner.strict_loading_n_plus_one_only? && reflection.macro == :has_many
|
237
|
+
record.strict_loading!
|
238
|
+
else
|
239
|
+
record.strict_loading!(false, mode: owner.strict_loading_mode)
|
240
|
+
end
|
241
|
+
end
|
228
242
|
end
|
229
243
|
|
230
|
-
def
|
244
|
+
def skip_strict_loading(&block)
|
245
|
+
skip_strict_loading_was = @skip_strict_loading
|
246
|
+
@skip_strict_loading = true
|
247
|
+
yield
|
248
|
+
ensure
|
249
|
+
@skip_strict_loading = skip_strict_loading_was
|
250
|
+
end
|
251
|
+
|
252
|
+
def violates_strict_loading?
|
253
|
+
return if @skip_strict_loading
|
254
|
+
|
255
|
+
return unless owner.validation_context.nil?
|
256
|
+
|
231
257
|
return reflection.strict_loading? if reflection.options.key?(:strict_loading)
|
232
258
|
|
233
|
-
owner.strict_loading?
|
259
|
+
owner.strict_loading? && !owner.strict_loading_n_plus_one_only?
|
234
260
|
end
|
235
261
|
|
236
262
|
# The scope for this association.
|
@@ -241,7 +267,11 @@ module ActiveRecord
|
|
241
267
|
# actually gets built.
|
242
268
|
def association_scope
|
243
269
|
if klass
|
244
|
-
@association_scope ||=
|
270
|
+
@association_scope ||= if disable_joins
|
271
|
+
DisableJoinsAssociationScope.scope(self)
|
272
|
+
else
|
273
|
+
AssociationScope.scope(self)
|
274
|
+
end
|
245
275
|
end
|
246
276
|
end
|
247
277
|
|
@@ -273,7 +303,7 @@ module ActiveRecord
|
|
273
303
|
|
274
304
|
# Raises ActiveRecord::AssociationTypeMismatch unless +record+ is of
|
275
305
|
# the kind of the class of the associated objects. Meant to be used as
|
276
|
-
# a
|
306
|
+
# a safety check when you are about to assign an associated record.
|
277
307
|
def raise_on_type_mismatch!(record)
|
278
308
|
unless record.is_a?(reflection.klass)
|
279
309
|
fresh_class = reflection.class_name.safe_constantize
|
@@ -306,7 +336,8 @@ module ActiveRecord
|
|
306
336
|
|
307
337
|
# Returns true if record contains the foreign_key
|
308
338
|
def foreign_key_for?(record)
|
309
|
-
|
339
|
+
foreign_key = Array(reflection.foreign_key)
|
340
|
+
foreign_key.all? { |key| record._has_attribute?(key) }
|
310
341
|
end
|
311
342
|
|
312
343
|
# This should be implemented to return the values of the relevant key(s) on the owner,
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
5
|
-
class AssociationScope
|
5
|
+
class AssociationScope # :nodoc:
|
6
6
|
def self.scope(association)
|
7
7
|
INSTANCE.scope(association)
|
8
8
|
end
|
@@ -35,7 +35,7 @@ module ActiveRecord
|
|
35
35
|
binds = []
|
36
36
|
last_reflection = chain.last
|
37
37
|
|
38
|
-
binds
|
38
|
+
binds.push(*last_reflection.join_id_for(owner))
|
39
39
|
if last_reflection.type
|
40
40
|
binds << owner.class.polymorphic_name
|
41
41
|
end
|
@@ -56,12 +56,15 @@ module ActiveRecord
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def last_chain_scope(scope, reflection, owner)
|
59
|
-
primary_key = reflection.join_primary_key
|
60
|
-
foreign_key = reflection.join_foreign_key
|
59
|
+
primary_key = Array(reflection.join_primary_key)
|
60
|
+
foreign_key = Array(reflection.join_foreign_key)
|
61
61
|
|
62
62
|
table = reflection.aliased_table
|
63
|
-
|
64
|
-
|
63
|
+
primary_key_foreign_key_pairs = primary_key.zip(foreign_key)
|
64
|
+
primary_key_foreign_key_pairs.each do |join_key, foreign_key|
|
65
|
+
value = transform_value(owner._read_attribute(foreign_key))
|
66
|
+
scope = apply_scope(scope, table, join_key, value)
|
67
|
+
end
|
65
68
|
|
66
69
|
if reflection.type
|
67
70
|
polymorphic_type = transform_value(owner.class.polymorphic_name)
|
@@ -76,19 +79,23 @@ module ActiveRecord
|
|
76
79
|
end
|
77
80
|
|
78
81
|
def next_chain_scope(scope, reflection, next_reflection)
|
79
|
-
primary_key = reflection.join_primary_key
|
80
|
-
foreign_key = reflection.join_foreign_key
|
82
|
+
primary_key = Array(reflection.join_primary_key)
|
83
|
+
foreign_key = Array(reflection.join_foreign_key)
|
81
84
|
|
82
85
|
table = reflection.aliased_table
|
83
86
|
foreign_table = next_reflection.aliased_table
|
84
|
-
|
87
|
+
|
88
|
+
primary_key_foreign_key_pairs = primary_key.zip(foreign_key)
|
89
|
+
constraints = primary_key_foreign_key_pairs.map do |join_primary_key, foreign_key|
|
90
|
+
table[join_primary_key].eq(foreign_table[foreign_key])
|
91
|
+
end.inject(&:and)
|
85
92
|
|
86
93
|
if reflection.type
|
87
94
|
value = transform_value(next_reflection.klass.polymorphic_name)
|
88
95
|
scope = apply_scope(scope, table, reflection.type, value)
|
89
96
|
end
|
90
97
|
|
91
|
-
scope.joins!(join(foreign_table,
|
98
|
+
scope.joins!(join(foreign_table, constraints))
|
92
99
|
end
|
93
100
|
|
94
101
|
class ReflectionProxy < SimpleDelegator # :nodoc:
|
@@ -123,8 +130,6 @@ module ActiveRecord
|
|
123
130
|
|
124
131
|
chain_head = chain.first
|
125
132
|
chain.reverse_each do |reflection|
|
126
|
-
# Exclude the scope of the association itself, because that
|
127
|
-
# was already merged in the #scope method.
|
128
133
|
reflection.constraints.each do |scope_chain_item|
|
129
134
|
item = eval_scope(reflection, scope_chain_item, owner)
|
130
135
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
5
5
|
# = Active Record Belongs To Association
|
6
|
-
class BelongsToAssociation < SingularAssociation
|
6
|
+
class BelongsToAssociation < SingularAssociation # :nodoc:
|
7
7
|
def handle_dependency
|
8
8
|
return unless load_target
|
9
9
|
|
@@ -11,8 +11,13 @@ module ActiveRecord
|
|
11
11
|
when :destroy
|
12
12
|
raise ActiveRecord::Rollback unless target.destroy
|
13
13
|
when :destroy_async
|
14
|
-
|
15
|
-
|
14
|
+
if reflection.foreign_key.is_a?(Array)
|
15
|
+
primary_key_column = reflection.active_record_primary_key.map(&:to_sym)
|
16
|
+
id = reflection.foreign_key.map { |col| owner.public_send(col.to_sym) }
|
17
|
+
else
|
18
|
+
primary_key_column = reflection.active_record_primary_key.to_sym
|
19
|
+
id = owner.public_send(reflection.foreign_key.to_sym)
|
20
|
+
end
|
16
21
|
|
17
22
|
enqueue_destroy_association(
|
18
23
|
owner_model_name: owner.class.to_s,
|
@@ -55,7 +60,8 @@ module ActiveRecord
|
|
55
60
|
|
56
61
|
def decrement_counters_before_last_save
|
57
62
|
if reflection.polymorphic?
|
58
|
-
|
63
|
+
model_type_was = owner.attribute_before_last_save(reflection.foreign_type)
|
64
|
+
model_was = owner.class.polymorphic_class_for(model_type_was) if model_type_was
|
59
65
|
else
|
60
66
|
model_was = klass
|
61
67
|
end
|
@@ -68,6 +74,14 @@ module ActiveRecord
|
|
68
74
|
end
|
69
75
|
|
70
76
|
def target_changed?
|
77
|
+
owner.attribute_changed?(reflection.foreign_key) || (!foreign_key_present? && target&.new_record?)
|
78
|
+
end
|
79
|
+
|
80
|
+
def target_previously_changed?
|
81
|
+
owner.attribute_previously_changed?(reflection.foreign_key)
|
82
|
+
end
|
83
|
+
|
84
|
+
def saved_change_to_target?
|
71
85
|
owner.saved_change_to_attribute?(reflection.foreign_key)
|
72
86
|
end
|
73
87
|
|
@@ -77,6 +91,8 @@ module ActiveRecord
|
|
77
91
|
raise_on_type_mismatch!(record)
|
78
92
|
set_inverse_instance(record)
|
79
93
|
@updated = true
|
94
|
+
elsif target
|
95
|
+
remove_inverse_instance(target)
|
80
96
|
end
|
81
97
|
|
82
98
|
replace_keys(record, force: true)
|
@@ -108,10 +124,13 @@ module ActiveRecord
|
|
108
124
|
end
|
109
125
|
|
110
126
|
def replace_keys(record, force: false)
|
111
|
-
|
127
|
+
target_key_values = record ? Array(primary_key(record.class)).map { |key| record._read_attribute(key) } : []
|
128
|
+
reflection_fk = Array(reflection.foreign_key)
|
112
129
|
|
113
|
-
if force || owner
|
114
|
-
|
130
|
+
if force || reflection_fk.map { |fk| owner._read_attribute(fk) } != target_key_values
|
131
|
+
reflection_fk.zip(target_key_values).each do |key, value|
|
132
|
+
owner[key] = value
|
133
|
+
end
|
115
134
|
end
|
116
135
|
end
|
117
136
|
|
@@ -120,12 +139,12 @@ module ActiveRecord
|
|
120
139
|
end
|
121
140
|
|
122
141
|
def foreign_key_present?
|
123
|
-
|
142
|
+
Array(reflection.foreign_key).all? { |fk| owner._read_attribute(fk) }
|
124
143
|
end
|
125
144
|
|
126
145
|
def invertible_for?(record)
|
127
146
|
inverse = inverse_reflection_for(record)
|
128
|
-
inverse && (inverse.has_one? ||
|
147
|
+
inverse && (inverse.has_one? || inverse.klass.has_many_inversing)
|
129
148
|
end
|
130
149
|
|
131
150
|
def stale_state
|
@@ -3,13 +3,21 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Associations
|
5
5
|
# = Active Record Belongs To Polymorphic Association
|
6
|
-
class BelongsToPolymorphicAssociation < BelongsToAssociation
|
6
|
+
class BelongsToPolymorphicAssociation < BelongsToAssociation # :nodoc:
|
7
7
|
def klass
|
8
8
|
type = owner[reflection.foreign_type]
|
9
9
|
type.presence && owner.class.polymorphic_class_for(type)
|
10
10
|
end
|
11
11
|
|
12
12
|
def target_changed?
|
13
|
+
super || owner.attribute_changed?(reflection.foreign_type)
|
14
|
+
end
|
15
|
+
|
16
|
+
def target_previously_changed?
|
17
|
+
super || owner.attribute_previously_changed?(reflection.foreign_type)
|
18
|
+
end
|
19
|
+
|
20
|
+
def saved_change_to_target?
|
13
21
|
super || owner.saved_change_to_attribute?(reflection.foreign_type)
|
14
22
|
end
|
15
23
|
|
@@ -19,7 +27,7 @@ module ActiveRecord
|
|
19
27
|
|
20
28
|
target_type = record ? record.class.polymorphic_name : nil
|
21
29
|
|
22
|
-
if force || owner
|
30
|
+
if force || owner._read_attribute(reflection.foreign_type) != target_type
|
23
31
|
owner[reflection.foreign_type] = target_type
|
24
32
|
end
|
25
33
|
end
|
@@ -12,14 +12,14 @@
|
|
12
12
|
# - HasManyAssociation
|
13
13
|
|
14
14
|
module ActiveRecord::Associations::Builder # :nodoc:
|
15
|
-
class Association
|
15
|
+
class Association # :nodoc:
|
16
16
|
class << self
|
17
17
|
attr_accessor :extensions
|
18
18
|
end
|
19
19
|
self.extensions = []
|
20
20
|
|
21
21
|
VALID_OPTIONS = [
|
22
|
-
:class_name, :anonymous_class, :primary_key, :foreign_key, :dependent, :validate, :inverse_of, :strict_loading
|
22
|
+
:class_name, :anonymous_class, :primary_key, :foreign_key, :dependent, :validate, :inverse_of, :strict_loading, :query_constraints
|
23
23
|
].freeze # :nodoc:
|
24
24
|
|
25
25
|
def self.build(model, name, scope, options, &block)
|
@@ -33,6 +33,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
33
33
|
define_accessors model, reflection
|
34
34
|
define_callbacks model, reflection
|
35
35
|
define_validations model, reflection
|
36
|
+
define_change_tracking_methods model, reflection
|
36
37
|
reflection
|
37
38
|
end
|
38
39
|
|
@@ -117,14 +118,18 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
117
118
|
# noop
|
118
119
|
end
|
119
120
|
|
121
|
+
def self.define_change_tracking_methods(model, reflection)
|
122
|
+
# noop
|
123
|
+
end
|
124
|
+
|
120
125
|
def self.valid_dependent_options
|
121
126
|
raise NotImplementedError
|
122
127
|
end
|
123
128
|
|
124
129
|
def self.check_dependent_options(dependent, model)
|
125
130
|
if dependent == :destroy_async && !model.destroy_association_async_job
|
126
|
-
err_message = "
|
127
|
-
raise ActiveRecord::
|
131
|
+
err_message = "A valid destroy_association_async_job is required to use `dependent: :destroy_async` on associations"
|
132
|
+
raise ActiveRecord::ConfigurationError, err_message
|
128
133
|
end
|
129
134
|
unless valid_dependent_options.include? dependent
|
130
135
|
raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{dependent}"
|
@@ -158,6 +163,7 @@ module ActiveRecord::Associations::Builder # :nodoc:
|
|
158
163
|
|
159
164
|
private_class_method :build_scope, :macro, :valid_options, :validate_options, :define_extensions,
|
160
165
|
:define_callbacks, :define_accessors, :define_readers, :define_writers, :define_validations,
|
161
|
-
:
|
166
|
+
:define_change_tracking_methods, :valid_dependent_options, :check_dependent_options,
|
167
|
+
:add_destroy_callbacks, :add_after_commit_jobs_callback
|
162
168
|
end
|
163
169
|
end
|