activerecord 7.0.8.7 → 7.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1339 -1572
- data/MIT-LICENSE +1 -1
- data/README.rdoc +15 -16
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +18 -3
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +14 -6
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +17 -9
- data/lib/active_record/associations/collection_proxy.rb +16 -11
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +20 -13
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency.rb +10 -8
- data/lib/active_record/associations/preloader/association.rb +27 -6
- data/lib/active_record/associations/preloader.rb +12 -9
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +193 -97
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/dirty.rb +40 -26
- data/lib/active_record/attribute_methods/primary_key.rb +76 -24
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +18 -5
- data/lib/active_record/attribute_methods/serialization.rb +150 -31
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +105 -21
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +55 -9
- data/lib/active_record/base.rb +7 -2
- data/lib/active_record/callbacks.rb +10 -24
- 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 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +163 -88
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +63 -43
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +109 -32
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +289 -122
- data/lib/active_record/connection_adapters/abstract/transaction.rb +280 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +502 -91
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +200 -108
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -143
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -12
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
- data/lib/active_record/connection_adapters/pool_config.rb +14 -5
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -29
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +351 -54
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +336 -168
- data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +42 -36
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +4 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -7
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +162 -77
- 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 +3 -1
- data/lib/active_record/connection_handling.rb +71 -94
- data/lib/active_record/core.rb +128 -138
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/database_config.rb +9 -3
- data/lib/active_record/database_configurations/hash_config.rb +22 -12
- data/lib/active_record/database_configurations/url_config.rb +17 -11
- data/lib/active_record/database_configurations.rb +86 -33
- data/lib/active_record/delegated_type.rb +8 -3
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +36 -18
- data/lib/active_record/encryption/encrypted_attribute_type.rb +17 -6
- data/lib/active_record/encryption/extended_deterministic_queries.rb +66 -54
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +2 -2
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/scheme.rb +19 -22
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +113 -26
- data/lib/active_record/errors.rb +89 -15
- data/lib/active_record/explain.rb +23 -3
- 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 +29 -8
- data/lib/active_record/fixtures.rb +119 -71
- data/lib/active_record/future_result.rb +30 -5
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +55 -8
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/internal_metadata.rb +118 -30
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +29 -12
- 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 +4 -0
- data/lib/active_record/middleware/database_selector.rb +5 -7
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +100 -4
- data/lib/active_record/migration/compatibility.rb +131 -5
- 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.rb +213 -109
- data/lib/active_record/model_schema.rb +47 -27
- data/lib/active_record/nested_attributes.rb +28 -3
- data/lib/active_record/normalization.rb +158 -0
- data/lib/active_record/persistence.rb +183 -33
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +77 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +15 -2
- data/lib/active_record/railtie.rb +107 -45
- data/lib/active_record/railties/controller_runtime.rb +10 -5
- data/lib/active_record/railties/databases.rake +139 -145
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +169 -45
- data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
- data/lib/active_record/relation/batches.rb +190 -61
- data/lib/active_record/relation/calculations.rb +152 -63
- data/lib/active_record/relation/delegation.rb +22 -8
- data/lib/active_record/relation/finder_methods.rb +85 -15
- data/lib/active_record/relation/merger.rb +2 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -2
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +26 -14
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +351 -62
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +76 -35
- data/lib/active_record/result.rb +19 -5
- data/lib/active_record/runtime_registry.rb +10 -1
- data/lib/active_record/sanitization.rb +51 -11
- data/lib/active_record/schema.rb +2 -3
- data/lib/active_record/schema_dumper.rb +41 -7
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +7 -5
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +10 -1
- data/lib/active_record/tasks/database_tasks.rb +127 -105
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -7
- data/lib/active_record/test_fixtures.rb +113 -96
- data/lib/active_record/timestamp.rb +26 -14
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +36 -10
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- 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 +47 -2
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +121 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.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/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +0 -8
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/predications.rb +2 -0
- data/lib/arel/table.rb +9 -5
- data/lib/arel/visitors/mysql.rb +8 -1
- data/lib/arel/visitors/to_sql.rb +81 -17
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +16 -2
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- 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
- metadata +52 -17
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
@@ -184,6 +184,22 @@ module ActiveRecord
|
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
187
|
+
class CompositePrimaryKeyMismatchError < ActiveRecordError # :nodoc:
|
188
|
+
attr_reader :reflection
|
189
|
+
|
190
|
+
def initialize(reflection = nil)
|
191
|
+
if reflection
|
192
|
+
if reflection.has_one? || reflection.collection?
|
193
|
+
super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.active_record_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
|
194
|
+
else
|
195
|
+
super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.association_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
|
196
|
+
end
|
197
|
+
else
|
198
|
+
super("Association primary key doesn't match with foreign key.")
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
187
203
|
class AmbiguousSourceReflectionForThroughAssociation < ActiveRecordError # :nodoc:
|
188
204
|
def initialize(klass, macro, association_name, options, possible_sources)
|
189
205
|
example_options = options.dup
|
@@ -319,8 +335,8 @@ module ActiveRecord
|
|
319
335
|
|
320
336
|
private
|
321
337
|
def init_internals
|
322
|
-
@association_cache = {}
|
323
338
|
super
|
339
|
+
@association_cache = {}
|
324
340
|
end
|
325
341
|
|
326
342
|
# Returns the specified association instance if it exists, +nil+ otherwise.
|
@@ -333,6 +349,8 @@ module ActiveRecord
|
|
333
349
|
@association_cache[name] = association
|
334
350
|
end
|
335
351
|
|
352
|
+
# = Active Record \Associations
|
353
|
+
#
|
336
354
|
# \Associations are a set of macro-like class methods for tying objects together through
|
337
355
|
# foreign keys. They express relationships like "Project has one Project Manager"
|
338
356
|
# or "Project belongs to a Portfolio". Each macro adds a number of methods to the
|
@@ -349,23 +367,42 @@ module ActiveRecord
|
|
349
367
|
#
|
350
368
|
# The project class now has the following methods (and more) to ease the traversal and
|
351
369
|
# manipulation of its relationships:
|
352
|
-
#
|
353
|
-
#
|
354
|
-
#
|
355
|
-
#
|
356
|
-
#
|
357
|
-
#
|
358
|
-
#
|
370
|
+
#
|
371
|
+
# project = Project.first
|
372
|
+
# project.portfolio
|
373
|
+
# project.portfolio = Portfolio.first
|
374
|
+
# project.reload_portfolio
|
375
|
+
#
|
376
|
+
# project.project_manager
|
377
|
+
# project.project_manager = ProjectManager.first
|
378
|
+
# project.reload_project_manager
|
379
|
+
#
|
380
|
+
# project.milestones.empty?
|
381
|
+
# project.milestones.size
|
382
|
+
# project.milestones
|
383
|
+
# project.milestones << Milestone.first
|
384
|
+
# project.milestones.delete(Milestone.first)
|
385
|
+
# project.milestones.destroy(Milestone.first)
|
386
|
+
# project.milestones.find(Milestone.first.id)
|
387
|
+
# project.milestones.build
|
388
|
+
# project.milestones.create
|
389
|
+
#
|
390
|
+
# project.categories.empty?
|
391
|
+
# project.categories.size
|
392
|
+
# project.categories
|
393
|
+
# project.categories << Category.first
|
394
|
+
# project.categories.delete(category1)
|
395
|
+
# project.categories.destroy(category1)
|
359
396
|
#
|
360
397
|
# === A word of warning
|
361
398
|
#
|
362
399
|
# Don't create associations that have the same name as {instance methods}[rdoc-ref:ActiveRecord::Core] of
|
363
|
-
#
|
364
|
-
# its model, using an association with the same name as one provided by
|
365
|
-
# For instance, +attributes+ and +connection+ would be bad choices for association names, because those names already exist in the list of
|
400
|
+
# +ActiveRecord::Base+. Since the association adds a method with that name to
|
401
|
+
# its model, using an association with the same name as one provided by +ActiveRecord::Base+ will override the method inherited through +ActiveRecord::Base+ and will break things.
|
402
|
+
# For instance, +attributes+ and +connection+ would be bad choices for association names, because those names already exist in the list of +ActiveRecord::Base+ instance methods.
|
366
403
|
#
|
367
404
|
# == Auto-generated methods
|
368
|
-
# See also Instance Public methods below for more details.
|
405
|
+
# See also "Instance Public methods" below ( from #belongs_to ) for more details.
|
369
406
|
#
|
370
407
|
# === Singular associations (one-to-one)
|
371
408
|
# | | belongs_to |
|
@@ -611,6 +648,7 @@ module ActiveRecord
|
|
611
648
|
# def log_after_remove(record)
|
612
649
|
# # ...
|
613
650
|
# end
|
651
|
+
# end
|
614
652
|
#
|
615
653
|
# It's possible to stack callbacks by passing them as an array. Example:
|
616
654
|
#
|
@@ -1025,45 +1063,45 @@ module ActiveRecord
|
|
1025
1063
|
# Indexes are appended for any more successive uses of the table name.
|
1026
1064
|
#
|
1027
1065
|
# Post.joins(:comments)
|
1028
|
-
# #
|
1066
|
+
# # SELECT ... FROM posts INNER JOIN comments ON ...
|
1029
1067
|
# Post.joins(:special_comments) # STI
|
1030
|
-
# #
|
1068
|
+
# # SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
|
1031
1069
|
# Post.joins(:comments, :special_comments) # special_comments is the reflection name, posts is the parent table name
|
1032
|
-
# #
|
1070
|
+
# # SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
|
1033
1071
|
#
|
1034
1072
|
# Acts as tree example:
|
1035
1073
|
#
|
1036
1074
|
# TreeMixin.joins(:children)
|
1037
|
-
# #
|
1075
|
+
# # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
1038
1076
|
# TreeMixin.joins(children: :parent)
|
1039
|
-
# #
|
1040
|
-
#
|
1077
|
+
# # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
1078
|
+
# # INNER JOIN parents_mixins ...
|
1041
1079
|
# TreeMixin.joins(children: {parent: :children})
|
1042
|
-
# #
|
1043
|
-
#
|
1044
|
-
#
|
1080
|
+
# # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
1081
|
+
# # INNER JOIN parents_mixins ...
|
1082
|
+
# # INNER JOIN mixins childrens_mixins_2
|
1045
1083
|
#
|
1046
1084
|
# Has and Belongs to Many join tables use the same idea, but add a <tt>_join</tt> suffix:
|
1047
1085
|
#
|
1048
1086
|
# Post.joins(:categories)
|
1049
|
-
# #
|
1087
|
+
# # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
1050
1088
|
# Post.joins(categories: :posts)
|
1051
|
-
# #
|
1052
|
-
#
|
1089
|
+
# # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
1090
|
+
# # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
1053
1091
|
# Post.joins(categories: {posts: :categories})
|
1054
|
-
# #
|
1055
|
-
#
|
1056
|
-
#
|
1092
|
+
# # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
1093
|
+
# # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
1094
|
+
# # INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
|
1057
1095
|
#
|
1058
1096
|
# If you wish to specify your own custom joins using ActiveRecord::QueryMethods#joins method, those table
|
1059
1097
|
# names will take precedence over the eager associations:
|
1060
1098
|
#
|
1061
1099
|
# Post.joins(:comments).joins("inner join comments ...")
|
1062
|
-
# #
|
1100
|
+
# # SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
|
1063
1101
|
# Post.joins(:comments, :special_comments).joins("inner join comments ...")
|
1064
|
-
# #
|
1065
|
-
#
|
1066
|
-
#
|
1102
|
+
# # SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
|
1103
|
+
# # INNER JOIN comments special_comments_posts ...
|
1104
|
+
# # INNER JOIN comments ...
|
1067
1105
|
#
|
1068
1106
|
# Table aliases are automatically truncated according to the maximum length of table identifiers
|
1069
1107
|
# according to the specific database.
|
@@ -1144,7 +1182,8 @@ module ActiveRecord
|
|
1144
1182
|
# belongs_to :dungeon, inverse_of: :evil_wizard
|
1145
1183
|
# end
|
1146
1184
|
#
|
1147
|
-
# For more information, see the documentation for the +:inverse_of+ option
|
1185
|
+
# For more information, see the documentation for the +:inverse_of+ option and the
|
1186
|
+
# {Active Record Associations guide}[https://guides.rubyonrails.org/association_basics.html#bi-directional-associations].
|
1148
1187
|
#
|
1149
1188
|
# == Deleting from associations
|
1150
1189
|
#
|
@@ -1166,7 +1205,7 @@ module ActiveRecord
|
|
1166
1205
|
# specific association types. When no option is given, the behavior is to do nothing
|
1167
1206
|
# with the associated records when destroying a record.
|
1168
1207
|
#
|
1169
|
-
# Note that <tt>:dependent</tt> is implemented using Rails' callback
|
1208
|
+
# Note that <tt>:dependent</tt> is implemented using \Rails' callback
|
1170
1209
|
# system, which works by processing callbacks in order. Therefore, other
|
1171
1210
|
# callbacks declared either before or after the <tt>:dependent</tt> option
|
1172
1211
|
# can affect what it does.
|
@@ -1302,23 +1341,32 @@ module ActiveRecord
|
|
1302
1341
|
#
|
1303
1342
|
# === Example
|
1304
1343
|
#
|
1305
|
-
#
|
1306
|
-
#
|
1307
|
-
#
|
1308
|
-
#
|
1309
|
-
#
|
1310
|
-
#
|
1311
|
-
#
|
1312
|
-
#
|
1313
|
-
#
|
1314
|
-
#
|
1315
|
-
#
|
1316
|
-
#
|
1317
|
-
#
|
1318
|
-
#
|
1319
|
-
#
|
1320
|
-
#
|
1321
|
-
#
|
1344
|
+
# class Firm < ActiveRecord::Base
|
1345
|
+
# has_many :clients
|
1346
|
+
# end
|
1347
|
+
#
|
1348
|
+
# Declaring <tt>has_many :clients</tt> adds the following methods (and more):
|
1349
|
+
#
|
1350
|
+
# firm = Firm.find(2)
|
1351
|
+
# client = Client.find(6)
|
1352
|
+
#
|
1353
|
+
# firm.clients # similar to Client.where(firm_id: 2)
|
1354
|
+
# firm.clients << client
|
1355
|
+
# firm.clients.delete(client)
|
1356
|
+
# firm.clients.destroy(client)
|
1357
|
+
# firm.clients = [client]
|
1358
|
+
# firm.client_ids
|
1359
|
+
# firm.client_ids = [6]
|
1360
|
+
# firm.clients.clear
|
1361
|
+
# firm.clients.empty? # similar to firm.clients.size == 0
|
1362
|
+
# firm.clients.size # similar to Client.count "firm_id = 2"
|
1363
|
+
# firm.clients.find # similar to Client.where(firm_id: 2).find(6)
|
1364
|
+
# firm.clients.exists?(name: 'ACME') # similar to Client.exists?(name: 'ACME', firm_id: 2)
|
1365
|
+
# firm.clients.build # similar to Client.new(firm_id: 2)
|
1366
|
+
# firm.clients.create # similar to Client.create(firm_id: 2)
|
1367
|
+
# firm.clients.create! # similar to Client.create!(firm_id: 2)
|
1368
|
+
# firm.clients.reload
|
1369
|
+
#
|
1322
1370
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1323
1371
|
#
|
1324
1372
|
# === Scopes
|
@@ -1357,8 +1405,8 @@ module ActiveRecord
|
|
1357
1405
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_many
|
1358
1406
|
# association will use "person_id" as the default <tt>:foreign_key</tt>.
|
1359
1407
|
#
|
1360
|
-
#
|
1361
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
1408
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
1409
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
1362
1410
|
# [:foreign_type]
|
1363
1411
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
1364
1412
|
# association. By default this is guessed to be the name of the polymorphic association
|
@@ -1370,7 +1418,7 @@ module ActiveRecord
|
|
1370
1418
|
# [:dependent]
|
1371
1419
|
# Controls what happens to the associated objects when
|
1372
1420
|
# their owner is destroyed. Note that these are implemented as
|
1373
|
-
# callbacks, and Rails executes callbacks in order. Therefore, other
|
1421
|
+
# callbacks, and \Rails executes callbacks in order. Therefore, other
|
1374
1422
|
# similar callbacks may affect the <tt>:dependent</tt> behavior, and the
|
1375
1423
|
# <tt>:dependent</tt> behavior may affect other callbacks.
|
1376
1424
|
#
|
@@ -1382,7 +1430,7 @@ module ActiveRecord
|
|
1382
1430
|
# * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
|
1383
1431
|
# * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Polymorphic type will also be nullified
|
1384
1432
|
# on polymorphic associations. Callbacks are not executed.
|
1385
|
-
# * <tt>:restrict_with_exception</tt> causes an
|
1433
|
+
# * <tt>:restrict_with_exception</tt> causes an ActiveRecord::DeleteRestrictionError exception to be raised if there are any associated records.
|
1386
1434
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
|
1387
1435
|
#
|
1388
1436
|
# If using with the <tt>:through</tt> option, the association on the join model must be
|
@@ -1414,7 +1462,7 @@ module ActiveRecord
|
|
1414
1462
|
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
1415
1463
|
# join model. This allows associated records to be built which will automatically create
|
1416
1464
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1417
|
-
#
|
1465
|
+
# and 'Setting Inverses' sections above.)
|
1418
1466
|
# [:disable_joins]
|
1419
1467
|
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1420
1468
|
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
@@ -1454,6 +1502,10 @@ module ActiveRecord
|
|
1454
1502
|
# [:ensuring_owner_was]
|
1455
1503
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
1456
1504
|
# associated records to be deleted in a background job.
|
1505
|
+
# [:query_constraints]
|
1506
|
+
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
1507
|
+
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
1508
|
+
# When the value is set the Array size must match associated model's primary key or `query_constraints` size.
|
1457
1509
|
#
|
1458
1510
|
# Option examples:
|
1459
1511
|
# has_many :comments, -> { order("posted_on") }
|
@@ -1466,6 +1518,7 @@ module ActiveRecord
|
|
1466
1518
|
# has_many :subscribers, through: :subscriptions, source: :user
|
1467
1519
|
# has_many :subscribers, through: :subscriptions, disable_joins: true
|
1468
1520
|
# has_many :comments, strict_loading: true
|
1521
|
+
# has_many :comments, query_constraints: [:blog_id, :post_id]
|
1469
1522
|
def has_many(name, scope = nil, **options, &extension)
|
1470
1523
|
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
|
1471
1524
|
Reflection.add_reflection self, name, reflection
|
@@ -1500,16 +1553,27 @@ module ActiveRecord
|
|
1500
1553
|
# if the record is invalid.
|
1501
1554
|
# [reload_association]
|
1502
1555
|
# Returns the associated object, forcing a database read.
|
1556
|
+
# [reset_association]
|
1557
|
+
# Unloads the associated object. The next access will query it from the database.
|
1503
1558
|
#
|
1504
1559
|
# === Example
|
1505
1560
|
#
|
1506
|
-
#
|
1507
|
-
#
|
1508
|
-
#
|
1509
|
-
#
|
1510
|
-
#
|
1511
|
-
#
|
1512
|
-
#
|
1561
|
+
# class Account < ActiveRecord::Base
|
1562
|
+
# has_one :beneficiary
|
1563
|
+
# end
|
1564
|
+
#
|
1565
|
+
# Declaring <tt>has_one :beneficiary</tt> adds the following methods (and more):
|
1566
|
+
#
|
1567
|
+
# account = Account.find(5)
|
1568
|
+
# beneficiary = Beneficiary.find(8)
|
1569
|
+
#
|
1570
|
+
# account.beneficiary # similar to Beneficiary.find_by(account_id: 5)
|
1571
|
+
# account.beneficiary = beneficiary # similar to beneficiary.update(account_id: 5)
|
1572
|
+
# account.build_beneficiary # similar to Beneficiary.new(account_id: 5)
|
1573
|
+
# account.create_beneficiary # similar to Beneficiary.create(account_id: 5)
|
1574
|
+
# account.create_beneficiary! # similar to Beneficiary.create!(account_id: 5)
|
1575
|
+
# account.reload_beneficiary
|
1576
|
+
# account.reset_beneficiary
|
1513
1577
|
#
|
1514
1578
|
# === Scopes
|
1515
1579
|
#
|
@@ -1543,7 +1607,7 @@ module ActiveRecord
|
|
1543
1607
|
# * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
|
1544
1608
|
# * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Polymorphic type column is also nullified
|
1545
1609
|
# on polymorphic associations. Callbacks are not executed.
|
1546
|
-
# * <tt>:restrict_with_exception</tt> causes an
|
1610
|
+
# * <tt>:restrict_with_exception</tt> causes an ActiveRecord::DeleteRestrictionError exception to be raised if there is an associated record
|
1547
1611
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
|
1548
1612
|
#
|
1549
1613
|
# Note that <tt>:dependent</tt> option is ignored when using <tt>:through</tt> option.
|
@@ -1552,8 +1616,8 @@ module ActiveRecord
|
|
1552
1616
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_one association
|
1553
1617
|
# will use "person_id" as the default <tt>:foreign_key</tt>.
|
1554
1618
|
#
|
1555
|
-
#
|
1556
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
1619
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
1620
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
1557
1621
|
# [:foreign_type]
|
1558
1622
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
1559
1623
|
# association. By default this is guessed to be the name of the polymorphic association
|
@@ -1579,7 +1643,7 @@ module ActiveRecord
|
|
1579
1643
|
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
1580
1644
|
# join model. This allows associated records to be built which will automatically create
|
1581
1645
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1582
|
-
#
|
1646
|
+
# and 'Setting Inverses' sections above.)
|
1583
1647
|
# [:disable_joins]
|
1584
1648
|
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1585
1649
|
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
@@ -1622,6 +1686,10 @@ module ActiveRecord
|
|
1622
1686
|
# [:ensuring_owner_was]
|
1623
1687
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
1624
1688
|
# associated records to be deleted in a background job.
|
1689
|
+
# [:query_constraints]
|
1690
|
+
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
1691
|
+
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
1692
|
+
# When the value is set the Array size must match associated model's primary key or `query_constraints` size.
|
1625
1693
|
#
|
1626
1694
|
# Option examples:
|
1627
1695
|
# has_one :credit_card, dependent: :destroy # destroys the associated credit card
|
@@ -1636,6 +1704,7 @@ module ActiveRecord
|
|
1636
1704
|
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
1637
1705
|
# has_one :credit_card, required: true
|
1638
1706
|
# has_one :credit_card, strict_loading: true
|
1707
|
+
# has_one :employment_record_book, query_constraints: [:organization_id, :employee_id]
|
1639
1708
|
def has_one(name, scope = nil, **options)
|
1640
1709
|
reflection = Builder::HasOne.build(self, name, scope, options)
|
1641
1710
|
Reflection.add_reflection self, name, reflection
|
@@ -1669,6 +1738,8 @@ module ActiveRecord
|
|
1669
1738
|
# if the record is invalid.
|
1670
1739
|
# [reload_association]
|
1671
1740
|
# Returns the associated object, forcing a database read.
|
1741
|
+
# [reset_association]
|
1742
|
+
# Unloads the associated object. The next access will query it from the database.
|
1672
1743
|
# [association_changed?]
|
1673
1744
|
# Returns true if a new associate object has been assigned and the next save will update the foreign key.
|
1674
1745
|
# [association_previously_changed?]
|
@@ -1676,16 +1747,24 @@ module ActiveRecord
|
|
1676
1747
|
#
|
1677
1748
|
# === Example
|
1678
1749
|
#
|
1679
|
-
#
|
1680
|
-
#
|
1681
|
-
#
|
1682
|
-
#
|
1683
|
-
#
|
1684
|
-
#
|
1685
|
-
#
|
1686
|
-
#
|
1687
|
-
#
|
1688
|
-
#
|
1750
|
+
# class Post < ActiveRecord::Base
|
1751
|
+
# belongs_to :author
|
1752
|
+
# end
|
1753
|
+
#
|
1754
|
+
# Declaring <tt>belongs_to :author</tt> adds the following methods (and more):
|
1755
|
+
#
|
1756
|
+
# post = Post.find(7)
|
1757
|
+
# author = Author.find(19)
|
1758
|
+
#
|
1759
|
+
# post.author # similar to Author.find(post.author_id)
|
1760
|
+
# post.author = author # similar to post.author_id = author.id
|
1761
|
+
# post.build_author # similar to post.author = Author.new
|
1762
|
+
# post.create_author # similar to post.author = Author.new; post.author.save; post.author
|
1763
|
+
# post.create_author! # similar to post.author = Author.new; post.author.save!; post.author
|
1764
|
+
# post.reload_author
|
1765
|
+
# post.reset_author
|
1766
|
+
# post.author_changed?
|
1767
|
+
# post.author_previously_changed?
|
1689
1768
|
#
|
1690
1769
|
# === Scopes
|
1691
1770
|
#
|
@@ -1700,6 +1779,8 @@ module ActiveRecord
|
|
1700
1779
|
#
|
1701
1780
|
# === Options
|
1702
1781
|
#
|
1782
|
+
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1783
|
+
#
|
1703
1784
|
# [:class_name]
|
1704
1785
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
1705
1786
|
# from the association name. So <tt>belongs_to :author</tt> will by default be linked to the Author class, but
|
@@ -1711,8 +1792,8 @@ module ActiveRecord
|
|
1711
1792
|
# <tt>belongs_to :favorite_person, class_name: "Person"</tt> will use a foreign key
|
1712
1793
|
# of "favorite_person_id".
|
1713
1794
|
#
|
1714
|
-
#
|
1715
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
1795
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
1796
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
1716
1797
|
# [:foreign_type]
|
1717
1798
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
1718
1799
|
# association. By default this is guessed to be the name of the association with a "_type"
|
@@ -1776,11 +1857,16 @@ module ActiveRecord
|
|
1776
1857
|
# [:default]
|
1777
1858
|
# Provide a callable (i.e. proc or lambda) to specify that the association should
|
1778
1859
|
# be initialized with a particular record before validation.
|
1860
|
+
# Please note that callable won't be executed if the record exists.
|
1779
1861
|
# [:strict_loading]
|
1780
1862
|
# Enforces strict loading every time the associated record is loaded through this association.
|
1781
1863
|
# [:ensuring_owner_was]
|
1782
1864
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
1783
1865
|
# associated records to be deleted in a background job.
|
1866
|
+
# [:query_constraints]
|
1867
|
+
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
1868
|
+
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
1869
|
+
# When the value is set the Array size must match associated model's primary key or `query_constraints` size.
|
1784
1870
|
#
|
1785
1871
|
# Option examples:
|
1786
1872
|
# belongs_to :firm, foreign_key: "client_of"
|
@@ -1796,6 +1882,7 @@ module ActiveRecord
|
|
1796
1882
|
# belongs_to :user, optional: true
|
1797
1883
|
# belongs_to :account, default: -> { company.account }
|
1798
1884
|
# belongs_to :account, strict_loading: true
|
1885
|
+
# belong_to :note, query_constraints: [:organization_id, :note_id]
|
1799
1886
|
def belongs_to(name, scope = nil, **options)
|
1800
1887
|
reflection = Builder::BelongsTo.build(self, name, scope, options)
|
1801
1888
|
Reflection.add_reflection self, name, reflection
|
@@ -1818,7 +1905,7 @@ module ActiveRecord
|
|
1818
1905
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1819
1906
|
# join table with a migration such as this:
|
1820
1907
|
#
|
1821
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.
|
1908
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.1]
|
1822
1909
|
# def change
|
1823
1910
|
# create_join_table :developers, :projects
|
1824
1911
|
# end
|
@@ -1879,22 +1966,31 @@ module ActiveRecord
|
|
1879
1966
|
#
|
1880
1967
|
# === Example
|
1881
1968
|
#
|
1882
|
-
#
|
1883
|
-
#
|
1884
|
-
#
|
1885
|
-
#
|
1886
|
-
#
|
1887
|
-
#
|
1888
|
-
#
|
1889
|
-
#
|
1890
|
-
#
|
1891
|
-
#
|
1892
|
-
#
|
1893
|
-
#
|
1894
|
-
#
|
1895
|
-
#
|
1896
|
-
#
|
1897
|
-
#
|
1969
|
+
# class Developer < ActiveRecord::Base
|
1970
|
+
# has_and_belongs_to_many :projects
|
1971
|
+
# end
|
1972
|
+
#
|
1973
|
+
# Declaring <tt>has_and_belongs_to_many :projects</tt> adds the following methods (and more):
|
1974
|
+
#
|
1975
|
+
# developer = Developer.find(11)
|
1976
|
+
# project = Project.find(9)
|
1977
|
+
#
|
1978
|
+
# developer.projects
|
1979
|
+
# developer.projects << project
|
1980
|
+
# developer.projects.delete(project)
|
1981
|
+
# developer.projects.destroy(project)
|
1982
|
+
# developer.projects = [project]
|
1983
|
+
# developer.project_ids
|
1984
|
+
# developer.project_ids = [9]
|
1985
|
+
# developer.projects.clear
|
1986
|
+
# developer.projects.empty?
|
1987
|
+
# developer.projects.size
|
1988
|
+
# developer.projects.find(9)
|
1989
|
+
# developer.projects.exists?(9)
|
1990
|
+
# developer.projects.build # similar to Project.new(developer_id: 11)
|
1991
|
+
# developer.projects.create # similar to Project.create(developer_id: 11)
|
1992
|
+
# developer.projects.reload
|
1993
|
+
#
|
1898
1994
|
# The declaration may include an +options+ hash to specialize the behavior of the association.
|
1899
1995
|
#
|
1900
1996
|
# === Scopes
|
@@ -1940,8 +2036,8 @@ module ActiveRecord
|
|
1940
2036
|
# a #has_and_belongs_to_many association to Project will use "person_id" as the
|
1941
2037
|
# default <tt>:foreign_key</tt>.
|
1942
2038
|
#
|
1943
|
-
#
|
1944
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
2039
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
2040
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
1945
2041
|
# [:association_foreign_key]
|
1946
2042
|
# Specify the foreign key used for the association on the receiving side of the association.
|
1947
2043
|
# By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
|
@@ -52,6 +52,23 @@ module ActiveRecord
|
|
52
52
|
attribute_before_type_cast(name)
|
53
53
|
end
|
54
54
|
|
55
|
+
# Returns the value of the attribute identified by +attr_name+ after
|
56
|
+
# serialization.
|
57
|
+
#
|
58
|
+
# class Book < ActiveRecord::Base
|
59
|
+
# enum status: { draft: 1, published: 2 }
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# book = Book.new(status: "published")
|
63
|
+
# book.read_attribute(:status) # => "published"
|
64
|
+
# book.read_attribute_for_database(:status) # => 2
|
65
|
+
def read_attribute_for_database(attr_name)
|
66
|
+
name = attr_name.to_s
|
67
|
+
name = self.class.attribute_aliases[name] || name
|
68
|
+
|
69
|
+
attribute_for_database(name)
|
70
|
+
end
|
71
|
+
|
55
72
|
# Returns a hash of attributes before typecasting and deserialization.
|
56
73
|
#
|
57
74
|
# class Task < ActiveRecord::Base
|