activerecord 7.0.8.7 → 7.1.0.beta1
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 +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
|