activerecord 7.0.0 → 7.2.1
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 +515 -1268
- data/MIT-LICENSE +1 -1
- data/README.rdoc +31 -31
- data/examples/performance.rb +2 -2
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations/alias_tracker.rb +25 -19
- data/lib/active_record/associations/association.rb +35 -12
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +23 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +22 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -7
- data/lib/active_record/associations/builder/has_many.rb +3 -4
- data/lib/active_record/associations/builder/has_one.rb +3 -4
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +28 -17
- data/lib/active_record/associations/collection_proxy.rb +36 -13
- data/lib/active_record/associations/errors.rb +265 -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 +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -25
- data/lib/active_record/associations/join_dependency.rb +18 -14
- data/lib/active_record/associations/nested_error.rb +47 -0
- data/lib/active_record/associations/preloader/association.rb +33 -8
- data/lib/active_record/associations/preloader/branch.rb +7 -1
- data/lib/active_record/associations/preloader/through_association.rb +2 -4
- data/lib/active_record/associations/preloader.rb +13 -10
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +378 -491
- data/lib/active_record/attribute_assignment.rb +1 -13
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
- data/lib/active_record/attribute_methods/dirty.rb +53 -35
- data/lib/active_record/attribute_methods/primary_key.rb +45 -25
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +8 -7
- data/lib/active_record/attribute_methods/serialization.rb +153 -70
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -6
- data/lib/active_record/attribute_methods/write.rb +6 -6
- data/lib/active_record/attribute_methods.rb +153 -40
- data/lib/active_record/attributes.rb +63 -48
- data/lib/active_record/autosave_association.rb +70 -38
- data/lib/active_record/base.rb +12 -8
- data/lib/active_record/callbacks.rb +16 -32
- 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 -34
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +124 -132
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +4 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +297 -88
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +160 -45
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +215 -63
- data/lib/active_record/connection_adapters/abstract/quoting.rb +83 -65
- 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 +163 -29
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +319 -135
- data/lib/active_record/connection_adapters/abstract/transaction.rb +367 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +512 -126
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +282 -119
- 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 +27 -140
- data/lib/active_record/connection_adapters/mysql/quoting.rb +64 -52
- 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 +45 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +152 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +101 -68
- data/lib/active_record/connection_adapters/pool_config.rb +20 -10
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +16 -3
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +101 -48
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +94 -61
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +6 -10
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +151 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +379 -66
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +370 -203
- data/lib/active_record/connection_adapters/schema_cache.rb +302 -79
- data/lib/active_record/connection_adapters/sqlite3/column.rb +62 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +60 -43
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +61 -46
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +20 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +64 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +321 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +229 -0
- data/lib/active_record/connection_adapters.rb +124 -1
- data/lib/active_record/connection_handling.rb +98 -106
- data/lib/active_record/core.rb +220 -177
- data/lib/active_record/counter_cache.rb +68 -34
- data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -2
- data/lib/active_record/database_configurations/database_config.rb +26 -5
- data/lib/active_record/database_configurations/hash_config.rb +52 -34
- data/lib/active_record/database_configurations/url_config.rb +37 -12
- data/lib/active_record/database_configurations.rb +88 -35
- data/lib/active_record/delegated_type.rb +40 -11
- 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 +1 -1
- data/lib/active_record/dynamic_matchers.rb +2 -2
- 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 +13 -14
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +8 -4
- data/lib/active_record/encryption/derived_secret_key_provider.rb +9 -3
- data/lib/active_record/encryption/deterministic_key_provider.rb +1 -1
- data/lib/active_record/encryption/encryptable_record.rb +47 -25
- data/lib/active_record/encryption/encrypted_attribute_type.rb +49 -14
- data/lib/active_record/encryption/encryptor.rb +25 -10
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +3 -3
- data/lib/active_record/encryption/extended_deterministic_queries.rb +83 -86
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +3 -3
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message.rb +1 -1
- data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
- data/lib/active_record/encryption/message_serializer.rb +6 -0
- data/lib/active_record/encryption/null_encryptor.rb +4 -0
- data/lib/active_record/encryption/properties.rb +4 -4
- data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
- data/lib/active_record/encryption/scheme.rb +23 -22
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +131 -27
- data/lib/active_record/errors.rb +151 -31
- data/lib/active_record/explain.rb +21 -12
- data/lib/active_record/explain_subscriber.rb +1 -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 +29 -8
- data/lib/active_record/fixtures.rb +169 -99
- data/lib/active_record/future_result.rb +47 -8
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +34 -18
- data/lib/active_record/insert_all.rb +72 -22
- data/lib/active_record/integration.rb +13 -10
- data/lib/active_record/internal_metadata.rb +124 -20
- data/lib/active_record/locking/optimistic.rb +39 -24
- data/lib/active_record/locking/pessimistic.rb +8 -5
- data/lib/active_record/log_subscriber.rb +28 -27
- 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 +18 -13
- data/lib/active_record/middleware/shard_selector.rb +7 -5
- data/lib/active_record/migration/command_recorder.rb +110 -13
- data/lib/active_record/migration/compatibility.rb +174 -64
- data/lib/active_record/migration/default_strategy.rb +22 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +292 -125
- data/lib/active_record/model_schema.rb +113 -112
- data/lib/active_record/nested_attributes.rb +35 -9
- data/lib/active_record/normalization.rb +163 -0
- data/lib/active_record/persistence.rb +177 -345
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +19 -25
- data/lib/active_record/query_logs.rb +102 -51
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +34 -9
- data/lib/active_record/railtie.rb +153 -100
- data/lib/active_record/railties/controller_runtime.rb +24 -10
- data/lib/active_record/railties/databases.rake +148 -152
- 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 +278 -69
- data/lib/active_record/relation/batches/batch_enumerator.rb +20 -5
- data/lib/active_record/relation/batches.rb +198 -63
- data/lib/active_record/relation/calculations.rb +293 -108
- data/lib/active_record/relation/delegation.rb +31 -20
- data/lib/active_record/relation/finder_methods.rb +93 -18
- data/lib/active_record/relation/merger.rb +6 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +38 -4
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +28 -16
- data/lib/active_record/relation/query_attribute.rb +25 -1
- data/lib/active_record/relation/query_methods.rb +625 -107
- data/lib/active_record/relation/record_fetch_warning.rb +3 -0
- data/lib/active_record/relation/spawn_methods.rb +5 -4
- data/lib/active_record/relation/where_clause.rb +7 -19
- data/lib/active_record/relation.rb +602 -96
- data/lib/active_record/result.rb +55 -52
- data/lib/active_record/runtime_registry.rb +63 -1
- data/lib/active_record/sanitization.rb +76 -30
- data/lib/active_record/schema.rb +39 -23
- data/lib/active_record/schema_dumper.rb +82 -30
- data/lib/active_record/schema_migration.rb +75 -24
- data/lib/active_record/scoping/default.rb +20 -12
- data/lib/active_record/scoping/named.rb +3 -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/serialization.rb +5 -0
- data/lib/active_record/signed_id.rb +29 -8
- data/lib/active_record/statement_cache.rb +7 -7
- data/lib/active_record/store.rb +16 -11
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +7 -3
- data/lib/active_record/tasks/database_tasks.rb +191 -121
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +17 -15
- data/lib/active_record/tasks/sqlite_database_tasks.rb +16 -7
- data/lib/active_record/test_fixtures.rb +174 -152
- data/lib/active_record/testing/query_assertions.rb +121 -0
- data/lib/active_record/timestamp.rb +31 -17
- data/lib/active_record/token_for.rb +123 -0
- data/lib/active_record/touch_later.rb +12 -7
- data/lib/active_record/transaction.rb +132 -0
- data/lib/active_record/transactions.rb +109 -27
- data/lib/active_record/translation.rb +1 -3
- 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/serialized.rb +9 -7
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type_caster/connection.rb +4 -4
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +12 -6
- 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 +63 -14
- data/lib/active_record/validations.rb +12 -5
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +266 -30
- data/lib/arel/alias_predication.rb +1 -1
- data/lib/arel/collectors/bind.rb +2 -0
- data/lib/arel/collectors/composite.rb +7 -0
- data/lib/arel/collectors/sql_string.rb +1 -1
- data/lib/arel/collectors/substitute_binds.rb +1 -1
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +1 -1
- data/lib/arel/nodes/binary.rb +6 -7
- data/lib/arel/nodes/bound_sql_literal.rb +65 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/filter.rb +1 -1
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/{and.rb → nary.rb} +9 -2
- data/lib/arel/nodes/node.rb +115 -5
- data/lib/arel/nodes/sql_literal.rb +13 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +6 -2
- data/lib/arel/predications.rb +3 -1
- data/lib/arel/select_manager.rb +1 -1
- data/lib/arel/table.rb +9 -5
- data/lib/arel/tree_manager.rb +8 -3
- data/lib/arel/update_manager.rb +2 -1
- data/lib/arel/visitors/dot.rb +1 -0
- data/lib/arel/visitors/mysql.rb +17 -5
- data/lib/arel/visitors/postgresql.rb +1 -12
- data/lib/arel/visitors/to_sql.rb +112 -34
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +21 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -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
- metadata +59 -17
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
|
@@ -1,252 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
|
-
class AssociationNotFoundError < ConfigurationError # :nodoc:
|
|
5
|
-
attr_reader :record, :association_name
|
|
6
|
-
|
|
7
|
-
def initialize(record = nil, association_name = nil)
|
|
8
|
-
@record = record
|
|
9
|
-
@association_name = association_name
|
|
10
|
-
if record && association_name
|
|
11
|
-
super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?")
|
|
12
|
-
else
|
|
13
|
-
super("Association was not found.")
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
|
18
|
-
include DidYouMean::Correctable
|
|
19
|
-
|
|
20
|
-
def corrections
|
|
21
|
-
if record && association_name
|
|
22
|
-
@corrections ||= begin
|
|
23
|
-
maybe_these = record.class.reflections.keys
|
|
24
|
-
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(association_name)
|
|
25
|
-
end
|
|
26
|
-
else
|
|
27
|
-
[]
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
class InverseOfAssociationNotFoundError < ActiveRecordError # :nodoc:
|
|
34
|
-
attr_reader :reflection, :associated_class
|
|
35
|
-
|
|
36
|
-
def initialize(reflection = nil, associated_class = nil)
|
|
37
|
-
if reflection
|
|
38
|
-
@reflection = reflection
|
|
39
|
-
@associated_class = associated_class.nil? ? reflection.klass : associated_class
|
|
40
|
-
super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
|
|
41
|
-
else
|
|
42
|
-
super("Could not find the inverse association.")
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
|
47
|
-
include DidYouMean::Correctable
|
|
48
|
-
|
|
49
|
-
def corrections
|
|
50
|
-
if reflection && associated_class
|
|
51
|
-
@corrections ||= begin
|
|
52
|
-
maybe_these = associated_class.reflections.keys
|
|
53
|
-
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:inverse_of].to_s)
|
|
54
|
-
end
|
|
55
|
-
else
|
|
56
|
-
[]
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
class InverseOfAssociationRecursiveError < ActiveRecordError # :nodoc:
|
|
63
|
-
attr_reader :reflection
|
|
64
|
-
def initialize(reflection = nil)
|
|
65
|
-
if reflection
|
|
66
|
-
@reflection = reflection
|
|
67
|
-
super("Inverse association #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{reflection.class_name}) is recursive.")
|
|
68
|
-
else
|
|
69
|
-
super("Inverse association is recursive.")
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
class HasManyThroughAssociationNotFoundError < ActiveRecordError # :nodoc:
|
|
75
|
-
attr_reader :owner_class, :reflection
|
|
76
|
-
|
|
77
|
-
def initialize(owner_class = nil, reflection = nil)
|
|
78
|
-
if owner_class && reflection
|
|
79
|
-
@owner_class = owner_class
|
|
80
|
-
@reflection = reflection
|
|
81
|
-
super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class.name}")
|
|
82
|
-
else
|
|
83
|
-
super("Could not find the association.")
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
|
88
|
-
include DidYouMean::Correctable
|
|
89
|
-
|
|
90
|
-
def corrections
|
|
91
|
-
if owner_class && reflection
|
|
92
|
-
@corrections ||= begin
|
|
93
|
-
maybe_these = owner_class.reflections.keys
|
|
94
|
-
maybe_these -= [reflection.name.to_s] # remove failing reflection
|
|
95
|
-
DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:through].to_s)
|
|
96
|
-
end
|
|
97
|
-
else
|
|
98
|
-
[]
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError # :nodoc:
|
|
105
|
-
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
|
106
|
-
if owner_class_name && reflection && source_reflection
|
|
107
|
-
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
|
|
108
|
-
else
|
|
109
|
-
super("Cannot have a has_many :through association.")
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
|
115
|
-
def initialize(owner_class_name = nil, reflection = nil)
|
|
116
|
-
if owner_class_name && reflection
|
|
117
|
-
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
|
|
118
|
-
else
|
|
119
|
-
super("Cannot have a has_many :through association.")
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError # :nodoc:
|
|
125
|
-
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
|
126
|
-
if owner_class_name && reflection && source_reflection
|
|
127
|
-
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
|
|
128
|
-
else
|
|
129
|
-
super("Cannot have a has_many :through association.")
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError # :nodoc:
|
|
135
|
-
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
|
136
|
-
if owner_class_name && reflection && through_reflection
|
|
137
|
-
super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
|
|
138
|
-
else
|
|
139
|
-
super("Cannot have a has_one :through association.")
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
class HasOneAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
|
145
|
-
def initialize(owner_class_name = nil, reflection = nil)
|
|
146
|
-
if owner_class_name && reflection
|
|
147
|
-
super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
|
|
148
|
-
else
|
|
149
|
-
super("Cannot have a has_one :through association.")
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError # :nodoc:
|
|
155
|
-
def initialize(reflection = nil)
|
|
156
|
-
if reflection
|
|
157
|
-
through_reflection = reflection.through_reflection
|
|
158
|
-
source_reflection_names = reflection.source_reflection_names
|
|
159
|
-
source_associations = reflection.through_reflection.klass._reflections.keys
|
|
160
|
-
super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')}?")
|
|
161
|
-
else
|
|
162
|
-
super("Could not find the source association(s).")
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
class HasManyThroughOrderError < ActiveRecordError # :nodoc:
|
|
168
|
-
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
|
169
|
-
if owner_class_name && reflection && through_reflection
|
|
170
|
-
super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through '#{owner_class_name}##{through_reflection.name}' before the through association is defined.")
|
|
171
|
-
else
|
|
172
|
-
super("Cannot have a has_many :through association before the through association is defined.")
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError # :nodoc:
|
|
178
|
-
def initialize(owner = nil, reflection = nil)
|
|
179
|
-
if owner && reflection
|
|
180
|
-
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")
|
|
181
|
-
else
|
|
182
|
-
super("Cannot modify association.")
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
class AmbiguousSourceReflectionForThroughAssociation < ActiveRecordError # :nodoc:
|
|
188
|
-
def initialize(klass, macro, association_name, options, possible_sources)
|
|
189
|
-
example_options = options.dup
|
|
190
|
-
example_options[:source] = possible_sources.first
|
|
191
|
-
|
|
192
|
-
super("Ambiguous source reflection for through association. Please " \
|
|
193
|
-
"specify a :source directive on your declaration like:\n" \
|
|
194
|
-
"\n" \
|
|
195
|
-
" class #{klass} < ActiveRecord::Base\n" \
|
|
196
|
-
" #{macro} :#{association_name}, #{example_options}\n" \
|
|
197
|
-
" end"
|
|
198
|
-
)
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
|
203
|
-
end
|
|
204
|
-
|
|
205
|
-
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
class ThroughNestedAssociationsAreReadonly < ActiveRecordError # :nodoc:
|
|
209
|
-
def initialize(owner = nil, reflection = nil)
|
|
210
|
-
if owner && reflection
|
|
211
|
-
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
|
|
212
|
-
else
|
|
213
|
-
super("Through nested associations are read-only.")
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
# This error is raised when trying to eager load a polymorphic association using a JOIN.
|
|
225
|
-
# Eager loading polymorphic associations is only possible with
|
|
226
|
-
# {ActiveRecord::Relation#preload}[rdoc-ref:QueryMethods#preload].
|
|
227
|
-
class EagerLoadPolymorphicError < ActiveRecordError
|
|
228
|
-
def initialize(reflection = nil)
|
|
229
|
-
if reflection
|
|
230
|
-
super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}")
|
|
231
|
-
else
|
|
232
|
-
super("Eager load polymorphic error.")
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
|
|
237
|
-
# This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
|
|
238
|
-
# (has_many, has_one) when there is at least 1 child associated instance.
|
|
239
|
-
# ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
|
|
240
|
-
class DeleteRestrictionError < ActiveRecordError # :nodoc:
|
|
241
|
-
def initialize(name = nil)
|
|
242
|
-
if name
|
|
243
|
-
super("Cannot delete record because of dependent #{name}")
|
|
244
|
-
else
|
|
245
|
-
super("Delete restriction error.")
|
|
246
|
-
end
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
|
|
250
4
|
# See ActiveRecord::Associations::ClassMethods for documentation.
|
|
251
5
|
module Associations # :nodoc:
|
|
252
6
|
extend ActiveSupport::Autoload
|
|
@@ -290,6 +44,7 @@ module ActiveRecord
|
|
|
290
44
|
def self.eager_load!
|
|
291
45
|
super
|
|
292
46
|
Preloader.eager_load!
|
|
47
|
+
JoinDependency.eager_load!
|
|
293
48
|
end
|
|
294
49
|
|
|
295
50
|
# Returns the association instance for the given name, instantiating it if it doesn't already exist
|
|
@@ -318,8 +73,8 @@ module ActiveRecord
|
|
|
318
73
|
|
|
319
74
|
private
|
|
320
75
|
def init_internals
|
|
321
|
-
@association_cache = {}
|
|
322
76
|
super
|
|
77
|
+
@association_cache = {}
|
|
323
78
|
end
|
|
324
79
|
|
|
325
80
|
# Returns the specified association instance if it exists, +nil+ otherwise.
|
|
@@ -332,6 +87,8 @@ module ActiveRecord
|
|
|
332
87
|
@association_cache[name] = association
|
|
333
88
|
end
|
|
334
89
|
|
|
90
|
+
# = Active Record \Associations
|
|
91
|
+
#
|
|
335
92
|
# \Associations are a set of macro-like class methods for tying objects together through
|
|
336
93
|
# foreign keys. They express relationships like "Project has one Project Manager"
|
|
337
94
|
# or "Project belongs to a Portfolio". Each macro adds a number of methods to the
|
|
@@ -348,23 +105,42 @@ module ActiveRecord
|
|
|
348
105
|
#
|
|
349
106
|
# The project class now has the following methods (and more) to ease the traversal and
|
|
350
107
|
# manipulation of its relationships:
|
|
351
|
-
#
|
|
352
|
-
#
|
|
353
|
-
#
|
|
354
|
-
#
|
|
355
|
-
#
|
|
356
|
-
#
|
|
357
|
-
#
|
|
108
|
+
#
|
|
109
|
+
# project = Project.first
|
|
110
|
+
# project.portfolio
|
|
111
|
+
# project.portfolio = Portfolio.first
|
|
112
|
+
# project.reload_portfolio
|
|
113
|
+
#
|
|
114
|
+
# project.project_manager
|
|
115
|
+
# project.project_manager = ProjectManager.first
|
|
116
|
+
# project.reload_project_manager
|
|
117
|
+
#
|
|
118
|
+
# project.milestones.empty?
|
|
119
|
+
# project.milestones.size
|
|
120
|
+
# project.milestones
|
|
121
|
+
# project.milestones << Milestone.first
|
|
122
|
+
# project.milestones.delete(Milestone.first)
|
|
123
|
+
# project.milestones.destroy(Milestone.first)
|
|
124
|
+
# project.milestones.find(Milestone.first.id)
|
|
125
|
+
# project.milestones.build
|
|
126
|
+
# project.milestones.create
|
|
127
|
+
#
|
|
128
|
+
# project.categories.empty?
|
|
129
|
+
# project.categories.size
|
|
130
|
+
# project.categories
|
|
131
|
+
# project.categories << Category.first
|
|
132
|
+
# project.categories.delete(category1)
|
|
133
|
+
# project.categories.destroy(category1)
|
|
358
134
|
#
|
|
359
135
|
# === A word of warning
|
|
360
136
|
#
|
|
361
137
|
# Don't create associations that have the same name as {instance methods}[rdoc-ref:ActiveRecord::Core] of
|
|
362
|
-
#
|
|
363
|
-
# its model, using an association with the same name as one provided by
|
|
364
|
-
# For instance, +attributes+ and +connection+ would be bad choices for association names, because those names already exist in the list of
|
|
138
|
+
# +ActiveRecord::Base+. Since the association adds a method with that name to
|
|
139
|
+
# 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.
|
|
140
|
+
# 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.
|
|
365
141
|
#
|
|
366
142
|
# == Auto-generated methods
|
|
367
|
-
# See also Instance Public methods below for more details.
|
|
143
|
+
# See also "Instance Public methods" below ( from #belongs_to ) for more details.
|
|
368
144
|
#
|
|
369
145
|
# === Singular associations (one-to-one)
|
|
370
146
|
# | | belongs_to |
|
|
@@ -431,7 +207,7 @@ module ActiveRecord
|
|
|
431
207
|
#
|
|
432
208
|
# == Cardinality and associations
|
|
433
209
|
#
|
|
434
|
-
# Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
|
|
210
|
+
# Active Record associations can be used to describe one-to-one, one-to-many, and many-to-many
|
|
435
211
|
# relationships between models. Each model uses an association to describe its role in
|
|
436
212
|
# the relation. The #belongs_to association is always used in the model that has
|
|
437
213
|
# the foreign key.
|
|
@@ -585,8 +361,11 @@ module ActiveRecord
|
|
|
585
361
|
# has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
|
|
586
362
|
# end
|
|
587
363
|
#
|
|
588
|
-
# Note: Joining
|
|
589
|
-
#
|
|
364
|
+
# Note: Joining or eager loading such associations is not possible because
|
|
365
|
+
# those operations happen before instance creation. Such associations
|
|
366
|
+
# _can_ be preloaded, but doing so will perform N+1 queries because there
|
|
367
|
+
# will be a different scope for each record (similar to preloading
|
|
368
|
+
# polymorphic scopes).
|
|
590
369
|
#
|
|
591
370
|
# == Association callbacks
|
|
592
371
|
#
|
|
@@ -594,22 +373,31 @@ module ActiveRecord
|
|
|
594
373
|
# you can also define callbacks that get triggered when you add an object to or remove an
|
|
595
374
|
# object from an association collection.
|
|
596
375
|
#
|
|
597
|
-
# class
|
|
598
|
-
#
|
|
376
|
+
# class Firm < ActiveRecord::Base
|
|
377
|
+
# has_many :clients,
|
|
378
|
+
# dependent: :destroy,
|
|
379
|
+
# after_add: :congratulate_client,
|
|
380
|
+
# after_remove: :log_after_remove
|
|
381
|
+
#
|
|
382
|
+
# def congratulate_client(record)
|
|
383
|
+
# # ...
|
|
384
|
+
# end
|
|
599
385
|
#
|
|
600
|
-
# def
|
|
601
|
-
# ...
|
|
386
|
+
# def log_after_remove(record)
|
|
387
|
+
# # ...
|
|
602
388
|
# end
|
|
603
389
|
# end
|
|
604
390
|
#
|
|
605
391
|
# It's possible to stack callbacks by passing them as an array. Example:
|
|
606
392
|
#
|
|
607
|
-
# class
|
|
608
|
-
#
|
|
609
|
-
#
|
|
393
|
+
# class Firm < ActiveRecord::Base
|
|
394
|
+
# has_many :clients,
|
|
395
|
+
# dependent: :destroy,
|
|
396
|
+
# after_add: [:congratulate_client, -> (firm, record) { firm.log << "after_adding#{record.id}" }],
|
|
397
|
+
# after_remove: :log_after_remove
|
|
610
398
|
# end
|
|
611
399
|
#
|
|
612
|
-
# Possible callbacks are: +before_add+, +after_add+, +before_remove
|
|
400
|
+
# Possible callbacks are: +before_add+, +after_add+, +before_remove+, and +after_remove+.
|
|
613
401
|
#
|
|
614
402
|
# If any of the +before_add+ callbacks throw an exception, the object will not be
|
|
615
403
|
# added to the collection.
|
|
@@ -617,6 +405,18 @@ module ActiveRecord
|
|
|
617
405
|
# Similarly, if any of the +before_remove+ callbacks throw an exception, the object
|
|
618
406
|
# will not be removed from the collection.
|
|
619
407
|
#
|
|
408
|
+
# Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example:
|
|
409
|
+
#
|
|
410
|
+
# * <tt>firm.clients.destroy(client)</tt>
|
|
411
|
+
# * <tt>firm.clients.destroy(*clients)</tt>
|
|
412
|
+
# * <tt>firm.clients.destroy_all</tt>
|
|
413
|
+
#
|
|
414
|
+
# +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks:
|
|
415
|
+
#
|
|
416
|
+
# * <tt>firm.clients.delete(client)</tt>
|
|
417
|
+
# * <tt>firm.clients.delete(*clients)</tt>
|
|
418
|
+
# * <tt>firm.clients.delete_all</tt>
|
|
419
|
+
#
|
|
620
420
|
# == Association extensions
|
|
621
421
|
#
|
|
622
422
|
# The proxy objects that control the access to associations can be extended through anonymous
|
|
@@ -988,7 +788,7 @@ module ActiveRecord
|
|
|
988
788
|
# query per addressable type.
|
|
989
789
|
# For example, if all the addressables are either of class Person or Company, then a total
|
|
990
790
|
# of 3 queries will be executed. The list of addressable types to load is determined on
|
|
991
|
-
# the back of the addresses loaded. This is not supported if Active Record has to
|
|
791
|
+
# the back of the addresses loaded. This is not supported if Active Record has to fall back
|
|
992
792
|
# to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError.
|
|
993
793
|
# The reason is that the parent model's type is a column value so its corresponding table
|
|
994
794
|
# name cannot be put in the +FROM+/+JOIN+ clauses of that query.
|
|
@@ -1001,45 +801,45 @@ module ActiveRecord
|
|
|
1001
801
|
# Indexes are appended for any more successive uses of the table name.
|
|
1002
802
|
#
|
|
1003
803
|
# Post.joins(:comments)
|
|
1004
|
-
# #
|
|
804
|
+
# # SELECT ... FROM posts INNER JOIN comments ON ...
|
|
1005
805
|
# Post.joins(:special_comments) # STI
|
|
1006
|
-
# #
|
|
806
|
+
# # SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
|
|
1007
807
|
# Post.joins(:comments, :special_comments) # special_comments is the reflection name, posts is the parent table name
|
|
1008
|
-
# #
|
|
808
|
+
# # SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
|
|
1009
809
|
#
|
|
1010
810
|
# Acts as tree example:
|
|
1011
811
|
#
|
|
1012
812
|
# TreeMixin.joins(:children)
|
|
1013
|
-
# #
|
|
813
|
+
# # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
|
1014
814
|
# TreeMixin.joins(children: :parent)
|
|
1015
|
-
# #
|
|
1016
|
-
#
|
|
815
|
+
# # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
|
816
|
+
# # INNER JOIN parents_mixins ...
|
|
1017
817
|
# TreeMixin.joins(children: {parent: :children})
|
|
1018
|
-
# #
|
|
1019
|
-
#
|
|
1020
|
-
#
|
|
818
|
+
# # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
|
819
|
+
# # INNER JOIN parents_mixins ...
|
|
820
|
+
# # INNER JOIN mixins childrens_mixins_2
|
|
1021
821
|
#
|
|
1022
822
|
# Has and Belongs to Many join tables use the same idea, but add a <tt>_join</tt> suffix:
|
|
1023
823
|
#
|
|
1024
824
|
# Post.joins(:categories)
|
|
1025
|
-
# #
|
|
825
|
+
# # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
|
1026
826
|
# Post.joins(categories: :posts)
|
|
1027
|
-
# #
|
|
1028
|
-
#
|
|
827
|
+
# # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
|
828
|
+
# # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
|
1029
829
|
# Post.joins(categories: {posts: :categories})
|
|
1030
|
-
# #
|
|
1031
|
-
#
|
|
1032
|
-
#
|
|
830
|
+
# # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
|
831
|
+
# # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
|
832
|
+
# # INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
|
|
1033
833
|
#
|
|
1034
834
|
# If you wish to specify your own custom joins using ActiveRecord::QueryMethods#joins method, those table
|
|
1035
835
|
# names will take precedence over the eager associations:
|
|
1036
836
|
#
|
|
1037
837
|
# Post.joins(:comments).joins("inner join comments ...")
|
|
1038
|
-
# #
|
|
838
|
+
# # SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
|
|
1039
839
|
# Post.joins(:comments, :special_comments).joins("inner join comments ...")
|
|
1040
|
-
# #
|
|
1041
|
-
#
|
|
1042
|
-
#
|
|
840
|
+
# # SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
|
|
841
|
+
# # INNER JOIN comments special_comments_posts ...
|
|
842
|
+
# # INNER JOIN comments ...
|
|
1043
843
|
#
|
|
1044
844
|
# Table aliases are automatically truncated according to the maximum length of table identifiers
|
|
1045
845
|
# according to the specific database.
|
|
@@ -1120,7 +920,8 @@ module ActiveRecord
|
|
|
1120
920
|
# belongs_to :dungeon, inverse_of: :evil_wizard
|
|
1121
921
|
# end
|
|
1122
922
|
#
|
|
1123
|
-
# For more information, see the documentation for the +:inverse_of+ option
|
|
923
|
+
# For more information, see the documentation for the +:inverse_of+ option and the
|
|
924
|
+
# {Active Record Associations guide}[https://guides.rubyonrails.org/association_basics.html#bi-directional-associations].
|
|
1124
925
|
#
|
|
1125
926
|
# == Deleting from associations
|
|
1126
927
|
#
|
|
@@ -1142,7 +943,7 @@ module ActiveRecord
|
|
|
1142
943
|
# specific association types. When no option is given, the behavior is to do nothing
|
|
1143
944
|
# with the associated records when destroying a record.
|
|
1144
945
|
#
|
|
1145
|
-
# Note that <tt>:dependent</tt> is implemented using Rails' callback
|
|
946
|
+
# Note that <tt>:dependent</tt> is implemented using \Rails' callback
|
|
1146
947
|
# system, which works by processing callbacks in order. Therefore, other
|
|
1147
948
|
# callbacks declared either before or after the <tt>:dependent</tt> option
|
|
1148
949
|
# can affect what it does.
|
|
@@ -1213,15 +1014,15 @@ module ActiveRecord
|
|
|
1213
1014
|
# +collection+ is a placeholder for the symbol passed as the +name+ argument, so
|
|
1214
1015
|
# <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
|
|
1215
1016
|
#
|
|
1216
|
-
# [collection]
|
|
1017
|
+
# [<tt>collection</tt>]
|
|
1217
1018
|
# Returns a Relation of all the associated objects.
|
|
1218
1019
|
# An empty Relation is returned if none are found.
|
|
1219
|
-
# [collection<<(object, ...)]
|
|
1020
|
+
# [<tt>collection<<(object, ...)</tt>]
|
|
1220
1021
|
# Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
|
|
1221
1022
|
# Note that this operation instantly fires update SQL without waiting for the save or update call on the
|
|
1222
1023
|
# parent object, unless the parent object is a new record.
|
|
1223
1024
|
# This will also run validations and callbacks of associated object(s).
|
|
1224
|
-
# [collection.delete(object, ...)]
|
|
1025
|
+
# [<tt>collection.delete(object, ...)</tt>]
|
|
1225
1026
|
# Removes one or more objects from the collection by setting their foreign keys to +NULL+.
|
|
1226
1027
|
# Objects will be in addition destroyed if they're associated with <tt>dependent: :destroy</tt>,
|
|
1227
1028
|
# and deleted if they're associated with <tt>dependent: :delete_all</tt>.
|
|
@@ -1229,75 +1030,84 @@ module ActiveRecord
|
|
|
1229
1030
|
# If the <tt>:through</tt> option is used, then the join records are deleted (rather than
|
|
1230
1031
|
# nullified) by default, but you can specify <tt>dependent: :destroy</tt> or
|
|
1231
1032
|
# <tt>dependent: :nullify</tt> to override this.
|
|
1232
|
-
# [collection.destroy(object, ...)]
|
|
1033
|
+
# [<tt>collection.destroy(object, ...)</tt>]
|
|
1233
1034
|
# Removes one or more objects from the collection by running <tt>destroy</tt> on
|
|
1234
1035
|
# each record, regardless of any dependent option, ensuring callbacks are run.
|
|
1235
1036
|
#
|
|
1236
1037
|
# If the <tt>:through</tt> option is used, then the join records are destroyed
|
|
1237
1038
|
# instead, not the objects themselves.
|
|
1238
|
-
# [collection=objects]
|
|
1039
|
+
# [<tt>collection=objects</tt>]
|
|
1239
1040
|
# Replaces the collections content by deleting and adding objects as appropriate. If the <tt>:through</tt>
|
|
1240
1041
|
# option is true callbacks in the join models are triggered except destroy callbacks, since deletion is
|
|
1241
1042
|
# direct by default. You can specify <tt>dependent: :destroy</tt> or
|
|
1242
1043
|
# <tt>dependent: :nullify</tt> to override this.
|
|
1243
|
-
# [collection_singular_ids]
|
|
1044
|
+
# [<tt>collection_singular_ids</tt>]
|
|
1244
1045
|
# Returns an array of the associated objects' ids
|
|
1245
|
-
# [collection_singular_ids=ids]
|
|
1046
|
+
# [<tt>collection_singular_ids=ids</tt>]
|
|
1246
1047
|
# Replace the collection with the objects identified by the primary keys in +ids+. This
|
|
1247
1048
|
# method loads the models and calls <tt>collection=</tt>. See above.
|
|
1248
|
-
# [collection.clear]
|
|
1049
|
+
# [<tt>collection.clear</tt>]
|
|
1249
1050
|
# Removes every object from the collection. This destroys the associated objects if they
|
|
1250
1051
|
# are associated with <tt>dependent: :destroy</tt>, deletes them directly from the
|
|
1251
1052
|
# database if <tt>dependent: :delete_all</tt>, otherwise sets their foreign keys to +NULL+.
|
|
1252
1053
|
# If the <tt>:through</tt> option is true no destroy callbacks are invoked on the join models.
|
|
1253
1054
|
# Join models are directly deleted.
|
|
1254
|
-
# [collection.empty
|
|
1055
|
+
# [<tt>collection.empty?</tt>]
|
|
1255
1056
|
# Returns +true+ if there are no associated objects.
|
|
1256
|
-
# [collection.size]
|
|
1057
|
+
# [<tt>collection.size</tt>]
|
|
1257
1058
|
# Returns the number of associated objects.
|
|
1258
|
-
# [collection.find(...)]
|
|
1059
|
+
# [<tt>collection.find(...)</tt>]
|
|
1259
1060
|
# Finds an associated object according to the same rules as ActiveRecord::FinderMethods#find.
|
|
1260
|
-
# [collection.exists?(...)]
|
|
1061
|
+
# [<tt>collection.exists?(...)</tt>]
|
|
1261
1062
|
# Checks whether an associated object with the given conditions exists.
|
|
1262
1063
|
# Uses the same rules as ActiveRecord::FinderMethods#exists?.
|
|
1263
|
-
# [collection.build(attributes = {}, ...)]
|
|
1064
|
+
# [<tt>collection.build(attributes = {}, ...)</tt>]
|
|
1264
1065
|
# Returns one or more new objects of the collection type that have been instantiated
|
|
1265
1066
|
# with +attributes+ and linked to this object through a foreign key, but have not yet
|
|
1266
1067
|
# been saved.
|
|
1267
|
-
# [collection.create(attributes = {})]
|
|
1068
|
+
# [<tt>collection.create(attributes = {})</tt>]
|
|
1268
1069
|
# Returns a new object of the collection type that has been instantiated
|
|
1269
1070
|
# with +attributes+, linked to this object through a foreign key, and that has already
|
|
1270
1071
|
# been saved (if it passed the validation). *Note*: This only works if the base model
|
|
1271
1072
|
# already exists in the DB, not if it is a new (unsaved) record!
|
|
1272
|
-
# [collection.create!(attributes = {})]
|
|
1073
|
+
# [<tt>collection.create!(attributes = {})</tt>]
|
|
1273
1074
|
# Does the same as <tt>collection.create</tt>, but raises ActiveRecord::RecordInvalid
|
|
1274
1075
|
# if the record is invalid.
|
|
1275
|
-
# [collection.reload]
|
|
1076
|
+
# [<tt>collection.reload</tt>]
|
|
1276
1077
|
# Returns a Relation of all of the associated objects, forcing a database read.
|
|
1277
1078
|
# An empty Relation is returned if none are found.
|
|
1278
1079
|
#
|
|
1279
|
-
#
|
|
1280
|
-
#
|
|
1281
|
-
#
|
|
1282
|
-
#
|
|
1283
|
-
#
|
|
1284
|
-
#
|
|
1285
|
-
#
|
|
1286
|
-
#
|
|
1287
|
-
#
|
|
1288
|
-
#
|
|
1289
|
-
#
|
|
1290
|
-
#
|
|
1291
|
-
#
|
|
1292
|
-
#
|
|
1293
|
-
#
|
|
1294
|
-
#
|
|
1295
|
-
#
|
|
1296
|
-
#
|
|
1297
|
-
#
|
|
1080
|
+
# ==== Example
|
|
1081
|
+
#
|
|
1082
|
+
# class Firm < ActiveRecord::Base
|
|
1083
|
+
# has_many :clients
|
|
1084
|
+
# end
|
|
1085
|
+
#
|
|
1086
|
+
# Declaring <tt>has_many :clients</tt> adds the following methods (and more):
|
|
1087
|
+
#
|
|
1088
|
+
# firm = Firm.find(2)
|
|
1089
|
+
# client = Client.find(6)
|
|
1090
|
+
#
|
|
1091
|
+
# firm.clients # similar to Client.where(firm_id: 2)
|
|
1092
|
+
# firm.clients << client
|
|
1093
|
+
# firm.clients.delete(client)
|
|
1094
|
+
# firm.clients.destroy(client)
|
|
1095
|
+
# firm.clients = [client]
|
|
1096
|
+
# firm.client_ids
|
|
1097
|
+
# firm.client_ids = [6]
|
|
1098
|
+
# firm.clients.clear
|
|
1099
|
+
# firm.clients.empty? # similar to firm.clients.size == 0
|
|
1100
|
+
# firm.clients.size # similar to Client.count "firm_id = 2"
|
|
1101
|
+
# firm.clients.find # similar to Client.where(firm_id: 2).find(6)
|
|
1102
|
+
# firm.clients.exists?(name: 'ACME') # similar to Client.exists?(name: 'ACME', firm_id: 2)
|
|
1103
|
+
# firm.clients.build # similar to Client.new(firm_id: 2)
|
|
1104
|
+
# firm.clients.create # similar to Client.create(firm_id: 2)
|
|
1105
|
+
# firm.clients.create! # similar to Client.create!(firm_id: 2)
|
|
1106
|
+
# firm.clients.reload
|
|
1107
|
+
#
|
|
1298
1108
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
|
1299
1109
|
#
|
|
1300
|
-
#
|
|
1110
|
+
# ==== Scopes
|
|
1301
1111
|
#
|
|
1302
1112
|
# You can pass a second argument +scope+ as a callable (i.e. proc or
|
|
1303
1113
|
# lambda) to retrieve a specific set of records or customize the generated
|
|
@@ -1308,10 +1118,10 @@ module ActiveRecord
|
|
|
1308
1118
|
# has_many :employees, -> { joins(:address) }
|
|
1309
1119
|
# has_many :posts, ->(blog) { where("max_post_length > ?", blog.max_post_length) }
|
|
1310
1120
|
#
|
|
1311
|
-
#
|
|
1121
|
+
# ==== Extensions
|
|
1312
1122
|
#
|
|
1313
1123
|
# The +extension+ argument allows you to pass a block into a has_many
|
|
1314
|
-
# association. This is useful for adding new finders, creators and other
|
|
1124
|
+
# association. This is useful for adding new finders, creators, and other
|
|
1315
1125
|
# factory-type methods to be used as part of the association.
|
|
1316
1126
|
#
|
|
1317
1127
|
# Extension examples:
|
|
@@ -1322,31 +1132,31 @@ module ActiveRecord
|
|
|
1322
1132
|
# end
|
|
1323
1133
|
# end
|
|
1324
1134
|
#
|
|
1325
|
-
#
|
|
1326
|
-
# [
|
|
1135
|
+
# ==== Options
|
|
1136
|
+
# [+:class_name+]
|
|
1327
1137
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
|
1328
1138
|
# from the association name. So <tt>has_many :products</tt> will by default be linked
|
|
1329
1139
|
# to the +Product+ class, but if the real class name is +SpecialProduct+, you'll have to
|
|
1330
1140
|
# specify it with this option.
|
|
1331
|
-
# [
|
|
1141
|
+
# [+:foreign_key+]
|
|
1332
1142
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
|
1333
1143
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_many
|
|
1334
1144
|
# association will use "person_id" as the default <tt>:foreign_key</tt>.
|
|
1335
1145
|
#
|
|
1336
|
-
#
|
|
1337
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
|
1338
|
-
# [
|
|
1146
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
|
1147
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
|
1148
|
+
# [+:foreign_type+]
|
|
1339
1149
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
|
1340
1150
|
# association. By default this is guessed to be the name of the polymorphic association
|
|
1341
1151
|
# specified on "as" option with a "_type" suffix. So a class that defines a
|
|
1342
1152
|
# <tt>has_many :tags, as: :taggable</tt> association will use "taggable_type" as the
|
|
1343
1153
|
# default <tt>:foreign_type</tt>.
|
|
1344
|
-
# [
|
|
1154
|
+
# [+:primary_key+]
|
|
1345
1155
|
# Specify the name of the column to use as the primary key for the association. By default this is +id+.
|
|
1346
|
-
# [
|
|
1156
|
+
# [+:dependent+]
|
|
1347
1157
|
# Controls what happens to the associated objects when
|
|
1348
1158
|
# their owner is destroyed. Note that these are implemented as
|
|
1349
|
-
# callbacks, and Rails executes callbacks in order. Therefore, other
|
|
1159
|
+
# callbacks, and \Rails executes callbacks in order. Therefore, other
|
|
1350
1160
|
# similar callbacks may affect the <tt>:dependent</tt> behavior, and the
|
|
1351
1161
|
# <tt>:dependent</tt> behavior may affect other callbacks.
|
|
1352
1162
|
#
|
|
@@ -1358,7 +1168,7 @@ module ActiveRecord
|
|
|
1358
1168
|
# * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
|
|
1359
1169
|
# * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Polymorphic type will also be nullified
|
|
1360
1170
|
# on polymorphic associations. Callbacks are not executed.
|
|
1361
|
-
# * <tt>:restrict_with_exception</tt> causes an
|
|
1171
|
+
# * <tt>:restrict_with_exception</tt> causes an ActiveRecord::DeleteRestrictionError exception to be raised if there are any associated records.
|
|
1362
1172
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
|
|
1363
1173
|
#
|
|
1364
1174
|
# If using with the <tt>:through</tt> option, the association on the join model must be
|
|
@@ -1370,12 +1180,12 @@ module ActiveRecord
|
|
|
1370
1180
|
# <tt>has_many :comments, -> { where published: true }, dependent: :destroy</tt> and <tt>destroy</tt> is
|
|
1371
1181
|
# called on a post, only published comments are destroyed. This means that any unpublished comments in the
|
|
1372
1182
|
# database would still contain a foreign key pointing to the now deleted post.
|
|
1373
|
-
# [
|
|
1183
|
+
# [+:counter_cache+]
|
|
1374
1184
|
# This option can be used to configure a custom named <tt>:counter_cache.</tt> You only need this option,
|
|
1375
1185
|
# when you customized the name of your <tt>:counter_cache</tt> on the #belongs_to association.
|
|
1376
|
-
# [
|
|
1186
|
+
# [+:as+]
|
|
1377
1187
|
# Specifies a polymorphic interface (See #belongs_to).
|
|
1378
|
-
# [
|
|
1188
|
+
# [+:through+]
|
|
1379
1189
|
# Specifies an association through which to perform the query. This can be any other type
|
|
1380
1190
|
# of association, including other <tt>:through</tt> associations. Options for <tt>:class_name</tt>,
|
|
1381
1191
|
# <tt>:primary_key</tt> and <tt>:foreign_key</tt> are ignored, as the association uses the
|
|
@@ -1390,24 +1200,24 @@ module ActiveRecord
|
|
|
1390
1200
|
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
|
1391
1201
|
# join model. This allows associated records to be built which will automatically create
|
|
1392
1202
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
|
1393
|
-
#
|
|
1394
|
-
# [
|
|
1203
|
+
# and 'Setting Inverses' sections above.)
|
|
1204
|
+
# [+:disable_joins+]
|
|
1395
1205
|
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
|
1396
1206
|
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
|
1397
|
-
# due to database limitations. This option is only applicable on
|
|
1398
|
-
#
|
|
1399
|
-
# [
|
|
1207
|
+
# due to database limitations. This option is only applicable on <tt>has_many :through</tt> associations as
|
|
1208
|
+
# +has_many+ alone do not perform a join.
|
|
1209
|
+
# [+:source+]
|
|
1400
1210
|
# Specifies the source association name used by #has_many <tt>:through</tt> queries.
|
|
1401
1211
|
# Only use it if the name cannot be inferred from the association.
|
|
1402
1212
|
# <tt>has_many :subscribers, through: :subscriptions</tt> will look for either <tt>:subscribers</tt> or
|
|
1403
1213
|
# <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
|
|
1404
|
-
# [
|
|
1214
|
+
# [+:source_type+]
|
|
1405
1215
|
# Specifies type of the source association used by #has_many <tt>:through</tt> queries where the source
|
|
1406
1216
|
# association is a polymorphic #belongs_to.
|
|
1407
|
-
# [
|
|
1217
|
+
# [+:validate+]
|
|
1408
1218
|
# When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
|
|
1409
1219
|
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
|
1410
|
-
# [
|
|
1220
|
+
# [+:autosave+]
|
|
1411
1221
|
# If true, always save the associated objects or destroy them if marked for destruction,
|
|
1412
1222
|
# when saving the parent object. If false, never save or destroy the associated objects.
|
|
1413
1223
|
# By default, only save associated objects that are new records. This option is implemented as a
|
|
@@ -1416,20 +1226,31 @@ module ActiveRecord
|
|
|
1416
1226
|
#
|
|
1417
1227
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
|
1418
1228
|
# <tt>:autosave</tt> to <tt>true</tt>.
|
|
1419
|
-
# [
|
|
1229
|
+
# [+:inverse_of+]
|
|
1420
1230
|
# Specifies the name of the #belongs_to association on the associated object
|
|
1421
1231
|
# that is the inverse of this #has_many association.
|
|
1422
1232
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
|
1423
|
-
# [
|
|
1233
|
+
# [+:extend+]
|
|
1424
1234
|
# Specifies a module or array of modules that will be extended into the association object returned.
|
|
1425
1235
|
# Useful for defining methods on associations, especially when they should be shared between multiple
|
|
1426
1236
|
# association objects.
|
|
1427
|
-
# [
|
|
1237
|
+
# [+:strict_loading+]
|
|
1428
1238
|
# When set to +true+, enforces strict loading every time the associated record is loaded through this
|
|
1429
1239
|
# association.
|
|
1430
|
-
# [
|
|
1240
|
+
# [+:ensuring_owner_was+]
|
|
1431
1241
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
|
1432
1242
|
# associated records to be deleted in a background job.
|
|
1243
|
+
# [+:query_constraints+]
|
|
1244
|
+
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
|
1245
|
+
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
|
1246
|
+
# When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
|
|
1247
|
+
# [+:index_errors+]
|
|
1248
|
+
# Allows differentiation of multiple validation errors from the association records, by including
|
|
1249
|
+
# an index in the error attribute name, e.g. +roles[2].level+.
|
|
1250
|
+
# When set to +true+, the index is based on association order, i.e. database order, with yet to be
|
|
1251
|
+
# persisted new records placed at the end.
|
|
1252
|
+
# When set to +:nested_attributes_order+, the index is based on the record order received by
|
|
1253
|
+
# nested attributes setter, when accepts_nested_attributes_for is used.
|
|
1433
1254
|
#
|
|
1434
1255
|
# Option examples:
|
|
1435
1256
|
# has_many :comments, -> { order("posted_on") }
|
|
@@ -1442,6 +1263,8 @@ module ActiveRecord
|
|
|
1442
1263
|
# has_many :subscribers, through: :subscriptions, source: :user
|
|
1443
1264
|
# has_many :subscribers, through: :subscriptions, disable_joins: true
|
|
1444
1265
|
# has_many :comments, strict_loading: true
|
|
1266
|
+
# has_many :comments, query_constraints: [:blog_id, :post_id]
|
|
1267
|
+
# has_many :comments, index_errors: :nested_attributes_order
|
|
1445
1268
|
def has_many(name, scope = nil, **options, &extension)
|
|
1446
1269
|
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
|
|
1447
1270
|
Reflection.add_reflection self, name, reflection
|
|
@@ -1457,37 +1280,48 @@ module ActiveRecord
|
|
|
1457
1280
|
# +association+ is a placeholder for the symbol passed as the +name+ argument, so
|
|
1458
1281
|
# <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.
|
|
1459
1282
|
#
|
|
1460
|
-
# [association]
|
|
1283
|
+
# [<tt>association</tt>]
|
|
1461
1284
|
# Returns the associated object. +nil+ is returned if none is found.
|
|
1462
|
-
# [association=(associate)]
|
|
1285
|
+
# [<tt>association=(associate)</tt>]
|
|
1463
1286
|
# Assigns the associate object, extracts the primary key, sets it as the foreign key,
|
|
1464
1287
|
# and saves the associate object. To avoid database inconsistencies, permanently deletes an existing
|
|
1465
1288
|
# associated object when assigning a new one, even if the new one isn't saved to database.
|
|
1466
|
-
# [build_association(attributes = {})]
|
|
1289
|
+
# [<tt>build_association(attributes = {})</tt>]
|
|
1467
1290
|
# Returns a new object of the associated type that has been instantiated
|
|
1468
1291
|
# with +attributes+ and linked to this object through a foreign key, but has not
|
|
1469
1292
|
# yet been saved.
|
|
1470
|
-
# [create_association(attributes = {})]
|
|
1293
|
+
# [<tt>create_association(attributes = {})</tt>]
|
|
1471
1294
|
# Returns a new object of the associated type that has been instantiated
|
|
1472
1295
|
# with +attributes+, linked to this object through a foreign key, and that
|
|
1473
1296
|
# has already been saved (if it passed the validation).
|
|
1474
|
-
# [create_association!(attributes = {})]
|
|
1297
|
+
# [<tt>create_association!(attributes = {})</tt>]
|
|
1475
1298
|
# Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
|
|
1476
1299
|
# if the record is invalid.
|
|
1477
|
-
# [reload_association]
|
|
1300
|
+
# [<tt>reload_association</tt>]
|
|
1478
1301
|
# Returns the associated object, forcing a database read.
|
|
1302
|
+
# [<tt>reset_association</tt>]
|
|
1303
|
+
# Unloads the associated object. The next access will query it from the database.
|
|
1479
1304
|
#
|
|
1480
|
-
#
|
|
1305
|
+
# ==== Example
|
|
1481
1306
|
#
|
|
1482
|
-
#
|
|
1483
|
-
#
|
|
1484
|
-
#
|
|
1485
|
-
# * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new(account_id: id)</tt>)
|
|
1486
|
-
# * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new(account_id: id); b.save; b</tt>)
|
|
1487
|
-
# * <tt>Account#create_beneficiary!</tt> (similar to <tt>b = Beneficiary.new(account_id: id); b.save!; b</tt>)
|
|
1488
|
-
# * <tt>Account#reload_beneficiary</tt>
|
|
1307
|
+
# class Account < ActiveRecord::Base
|
|
1308
|
+
# has_one :beneficiary
|
|
1309
|
+
# end
|
|
1489
1310
|
#
|
|
1490
|
-
#
|
|
1311
|
+
# Declaring <tt>has_one :beneficiary</tt> adds the following methods (and more):
|
|
1312
|
+
#
|
|
1313
|
+
# account = Account.find(5)
|
|
1314
|
+
# beneficiary = Beneficiary.find(8)
|
|
1315
|
+
#
|
|
1316
|
+
# account.beneficiary # similar to Beneficiary.find_by(account_id: 5)
|
|
1317
|
+
# account.beneficiary = beneficiary # similar to beneficiary.update(account_id: 5)
|
|
1318
|
+
# account.build_beneficiary # similar to Beneficiary.new(account_id: 5)
|
|
1319
|
+
# account.create_beneficiary # similar to Beneficiary.create(account_id: 5)
|
|
1320
|
+
# account.create_beneficiary! # similar to Beneficiary.create!(account_id: 5)
|
|
1321
|
+
# account.reload_beneficiary
|
|
1322
|
+
# account.reset_beneficiary
|
|
1323
|
+
#
|
|
1324
|
+
# ==== Scopes
|
|
1491
1325
|
#
|
|
1492
1326
|
# You can pass a second argument +scope+ as a callable (i.e. proc or
|
|
1493
1327
|
# lambda) to retrieve a specific record or customize the generated query
|
|
@@ -1498,16 +1332,16 @@ module ActiveRecord
|
|
|
1498
1332
|
# has_one :employer, -> { joins(:company) }
|
|
1499
1333
|
# has_one :latest_post, ->(blog) { where("created_at > ?", blog.enabled_at) }
|
|
1500
1334
|
#
|
|
1501
|
-
#
|
|
1335
|
+
# ==== Options
|
|
1502
1336
|
#
|
|
1503
1337
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
|
1504
1338
|
#
|
|
1505
1339
|
# Options are:
|
|
1506
|
-
# [
|
|
1340
|
+
# [+:class_name+]
|
|
1507
1341
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
|
1508
1342
|
# from the association name. So <tt>has_one :manager</tt> will by default be linked to the Manager class, but
|
|
1509
1343
|
# if the real class name is Person, you'll have to specify it with this option.
|
|
1510
|
-
# [
|
|
1344
|
+
# [+:dependent+]
|
|
1511
1345
|
# Controls what happens to the associated object when
|
|
1512
1346
|
# its owner is destroyed:
|
|
1513
1347
|
#
|
|
@@ -1519,28 +1353,28 @@ module ActiveRecord
|
|
|
1519
1353
|
# * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
|
|
1520
1354
|
# * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Polymorphic type column is also nullified
|
|
1521
1355
|
# on polymorphic associations. Callbacks are not executed.
|
|
1522
|
-
# * <tt>:restrict_with_exception</tt> causes an
|
|
1356
|
+
# * <tt>:restrict_with_exception</tt> causes an ActiveRecord::DeleteRestrictionError exception to be raised if there is an associated record
|
|
1523
1357
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
|
|
1524
1358
|
#
|
|
1525
1359
|
# Note that <tt>:dependent</tt> option is ignored when using <tt>:through</tt> option.
|
|
1526
|
-
# [
|
|
1360
|
+
# [+:foreign_key+]
|
|
1527
1361
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
|
1528
1362
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_one association
|
|
1529
1363
|
# will use "person_id" as the default <tt>:foreign_key</tt>.
|
|
1530
1364
|
#
|
|
1531
|
-
#
|
|
1532
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
|
1533
|
-
# [
|
|
1365
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
|
1366
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
|
1367
|
+
# [+:foreign_type+]
|
|
1534
1368
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
|
1535
1369
|
# association. By default this is guessed to be the name of the polymorphic association
|
|
1536
1370
|
# specified on "as" option with a "_type" suffix. So a class that defines a
|
|
1537
1371
|
# <tt>has_one :tag, as: :taggable</tt> association will use "taggable_type" as the
|
|
1538
1372
|
# default <tt>:foreign_type</tt>.
|
|
1539
|
-
# [
|
|
1373
|
+
# [+:primary_key+]
|
|
1540
1374
|
# Specify the method that returns the primary key used for the association. By default this is +id+.
|
|
1541
|
-
# [
|
|
1375
|
+
# [+:as+]
|
|
1542
1376
|
# Specifies a polymorphic interface (See #belongs_to).
|
|
1543
|
-
# [
|
|
1377
|
+
# [+:through+]
|
|
1544
1378
|
# Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>,
|
|
1545
1379
|
# <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
|
|
1546
1380
|
# source reflection. You can only use a <tt>:through</tt> query through a #has_one
|
|
@@ -1555,43 +1389,58 @@ module ActiveRecord
|
|
|
1555
1389
|
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
|
1556
1390
|
# join model. This allows associated records to be built which will automatically create
|
|
1557
1391
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
|
1558
|
-
#
|
|
1559
|
-
# [
|
|
1392
|
+
# and 'Setting Inverses' sections above.)
|
|
1393
|
+
# [+:disable_joins+]
|
|
1560
1394
|
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
|
1561
1395
|
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
|
1562
|
-
# due to database limitations. This option is only applicable on
|
|
1563
|
-
#
|
|
1564
|
-
# [
|
|
1396
|
+
# due to database limitations. This option is only applicable on <tt>has_one :through</tt> associations as
|
|
1397
|
+
# +has_one+ alone does not perform a join.
|
|
1398
|
+
# [+:source+]
|
|
1565
1399
|
# Specifies the source association name used by #has_one <tt>:through</tt> queries.
|
|
1566
1400
|
# Only use it if the name cannot be inferred from the association.
|
|
1567
1401
|
# <tt>has_one :favorite, through: :favorites</tt> will look for a
|
|
1568
1402
|
# <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
|
|
1569
|
-
# [
|
|
1403
|
+
# [+:source_type+]
|
|
1570
1404
|
# Specifies type of the source association used by #has_one <tt>:through</tt> queries where the source
|
|
1571
1405
|
# association is a polymorphic #belongs_to.
|
|
1572
|
-
# [
|
|
1406
|
+
# [+:validate+]
|
|
1573
1407
|
# When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
|
|
1574
1408
|
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
|
1575
|
-
# [
|
|
1576
|
-
# If true
|
|
1577
|
-
# when saving the parent object.
|
|
1578
|
-
#
|
|
1409
|
+
# [+:autosave+]
|
|
1410
|
+
# If +true+, always saves the associated object or destroys it if marked for destruction,
|
|
1411
|
+
# when saving the parent object.
|
|
1412
|
+
# If +false+, never save or destroy the associated object.
|
|
1413
|
+
#
|
|
1414
|
+
# By default, only saves the associated object if it's a new record. Setting this option
|
|
1415
|
+
# to +true+ also enables validations on the associated object unless explicitly disabled
|
|
1416
|
+
# with <tt>validate: false</tt>. This is because saving an object with invalid associated
|
|
1417
|
+
# objects would fail, so any associated objects will go through validation checks.
|
|
1579
1418
|
#
|
|
1580
1419
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
|
1581
1420
|
# <tt>:autosave</tt> to <tt>true</tt>.
|
|
1582
|
-
# [
|
|
1421
|
+
# [+:touch+]
|
|
1422
|
+
# If true, the associated object will be touched (the +updated_at+ / +updated_on+ attributes set to current time)
|
|
1423
|
+
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
|
1424
|
+
# will be updated with the current time in addition to the +updated_at+ / +updated_on+ attribute.
|
|
1425
|
+
# Please note that no validation will be performed when touching, and only the +after_touch+,
|
|
1426
|
+
# +after_commit+, and +after_rollback+ callbacks will be executed.
|
|
1427
|
+
# [+:inverse_of+]
|
|
1583
1428
|
# Specifies the name of the #belongs_to association on the associated object
|
|
1584
1429
|
# that is the inverse of this #has_one association.
|
|
1585
1430
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
|
1586
|
-
# [
|
|
1431
|
+
# [+:required+]
|
|
1587
1432
|
# When set to +true+, the association will also have its presence validated.
|
|
1588
1433
|
# This will validate the association itself, not the id. You can use
|
|
1589
1434
|
# +:inverse_of+ to avoid an extra query during validation.
|
|
1590
|
-
# [
|
|
1435
|
+
# [+:strict_loading+]
|
|
1591
1436
|
# Enforces strict loading every time the associated record is loaded through this association.
|
|
1592
|
-
# [
|
|
1437
|
+
# [+:ensuring_owner_was+]
|
|
1593
1438
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
|
1594
1439
|
# associated records to be deleted in a background job.
|
|
1440
|
+
# [+:query_constraints+]
|
|
1441
|
+
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
|
1442
|
+
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
|
1443
|
+
# When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
|
|
1595
1444
|
#
|
|
1596
1445
|
# Option examples:
|
|
1597
1446
|
# has_one :credit_card, dependent: :destroy # destroys the associated credit card
|
|
@@ -1606,6 +1455,7 @@ module ActiveRecord
|
|
|
1606
1455
|
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
|
1607
1456
|
# has_one :credit_card, required: true
|
|
1608
1457
|
# has_one :credit_card, strict_loading: true
|
|
1458
|
+
# has_one :employment_record_book, query_constraints: [:organization_id, :employee_id]
|
|
1609
1459
|
def has_one(name, scope = nil, **options)
|
|
1610
1460
|
reflection = Builder::HasOne.build(self, name, scope, options)
|
|
1611
1461
|
Reflection.add_reflection self, name, reflection
|
|
@@ -1622,42 +1472,52 @@ module ActiveRecord
|
|
|
1622
1472
|
# +association+ is a placeholder for the symbol passed as the +name+ argument, so
|
|
1623
1473
|
# <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>.
|
|
1624
1474
|
#
|
|
1625
|
-
# [association]
|
|
1475
|
+
# [<tt>association</tt>]
|
|
1626
1476
|
# Returns the associated object. +nil+ is returned if none is found.
|
|
1627
|
-
# [association=(associate)]
|
|
1477
|
+
# [<tt>association=(associate)</tt>]
|
|
1628
1478
|
# Assigns the associate object, extracts the primary key, and sets it as the foreign key.
|
|
1629
1479
|
# No modification or deletion of existing records takes place.
|
|
1630
|
-
# [build_association(attributes = {})]
|
|
1480
|
+
# [<tt>build_association(attributes = {})</tt>]
|
|
1631
1481
|
# Returns a new object of the associated type that has been instantiated
|
|
1632
1482
|
# with +attributes+ and linked to this object through a foreign key, but has not yet been saved.
|
|
1633
|
-
# [create_association(attributes = {})]
|
|
1483
|
+
# [<tt>create_association(attributes = {})</tt>]
|
|
1634
1484
|
# Returns a new object of the associated type that has been instantiated
|
|
1635
1485
|
# with +attributes+, linked to this object through a foreign key, and that
|
|
1636
1486
|
# has already been saved (if it passed the validation).
|
|
1637
|
-
# [create_association!(attributes = {})]
|
|
1487
|
+
# [<tt>create_association!(attributes = {})</tt>]
|
|
1638
1488
|
# Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
|
|
1639
1489
|
# if the record is invalid.
|
|
1640
|
-
# [reload_association]
|
|
1490
|
+
# [<tt>reload_association</tt>]
|
|
1641
1491
|
# Returns the associated object, forcing a database read.
|
|
1642
|
-
# [
|
|
1492
|
+
# [<tt>reset_association</tt>]
|
|
1493
|
+
# Unloads the associated object. The next access will query it from the database.
|
|
1494
|
+
# [<tt>association_changed?</tt>]
|
|
1643
1495
|
# Returns true if a new associate object has been assigned and the next save will update the foreign key.
|
|
1644
|
-
# [association_previously_changed
|
|
1496
|
+
# [<tt>association_previously_changed?</tt>]
|
|
1645
1497
|
# Returns true if the previous save updated the association to reference a new associate object.
|
|
1646
1498
|
#
|
|
1647
|
-
#
|
|
1648
|
-
#
|
|
1649
|
-
# A Post class declares <tt>belongs_to :author</tt>, which will add:
|
|
1650
|
-
# * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>)
|
|
1651
|
-
# * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>)
|
|
1652
|
-
# * <tt>Post#build_author</tt> (similar to <tt>post.author = Author.new</tt>)
|
|
1653
|
-
# * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
|
|
1654
|
-
# * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
|
|
1655
|
-
# * <tt>Post#reload_author</tt>
|
|
1656
|
-
# * <tt>Post#author_changed?</tt>
|
|
1657
|
-
# * <tt>Post#author_previously_changed?</tt>
|
|
1658
|
-
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
|
1499
|
+
# ==== Example
|
|
1659
1500
|
#
|
|
1660
|
-
#
|
|
1501
|
+
# class Post < ActiveRecord::Base
|
|
1502
|
+
# belongs_to :author
|
|
1503
|
+
# end
|
|
1504
|
+
#
|
|
1505
|
+
# Declaring <tt>belongs_to :author</tt> adds the following methods (and more):
|
|
1506
|
+
#
|
|
1507
|
+
# post = Post.find(7)
|
|
1508
|
+
# author = Author.find(19)
|
|
1509
|
+
#
|
|
1510
|
+
# post.author # similar to Author.find(post.author_id)
|
|
1511
|
+
# post.author = author # similar to post.author_id = author.id
|
|
1512
|
+
# post.build_author # similar to post.author = Author.new
|
|
1513
|
+
# post.create_author # similar to post.author = Author.new; post.author.save; post.author
|
|
1514
|
+
# post.create_author! # similar to post.author = Author.new; post.author.save!; post.author
|
|
1515
|
+
# post.reload_author
|
|
1516
|
+
# post.reset_author
|
|
1517
|
+
# post.author_changed?
|
|
1518
|
+
# post.author_previously_changed?
|
|
1519
|
+
#
|
|
1520
|
+
# ==== Scopes
|
|
1661
1521
|
#
|
|
1662
1522
|
# You can pass a second argument +scope+ as a callable (i.e. proc or
|
|
1663
1523
|
# lambda) to retrieve a specific record or customize the generated query
|
|
@@ -1668,56 +1528,68 @@ module ActiveRecord
|
|
|
1668
1528
|
# belongs_to :user, -> { joins(:friends) }
|
|
1669
1529
|
# belongs_to :level, ->(game) { where("game_level > ?", game.current_level) }
|
|
1670
1530
|
#
|
|
1671
|
-
#
|
|
1531
|
+
# ==== Options
|
|
1672
1532
|
#
|
|
1673
|
-
#
|
|
1533
|
+
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
|
1534
|
+
#
|
|
1535
|
+
# [+:class_name+]
|
|
1674
1536
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
|
1675
1537
|
# from the association name. So <tt>belongs_to :author</tt> will by default be linked to the Author class, but
|
|
1676
1538
|
# if the real class name is Person, you'll have to specify it with this option.
|
|
1677
|
-
# [
|
|
1539
|
+
# [+:foreign_key+]
|
|
1678
1540
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
|
1679
1541
|
# of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt>
|
|
1680
1542
|
# association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
|
|
1681
1543
|
# <tt>belongs_to :favorite_person, class_name: "Person"</tt> will use a foreign key
|
|
1682
1544
|
# of "favorite_person_id".
|
|
1683
1545
|
#
|
|
1684
|
-
#
|
|
1685
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
|
1686
|
-
# [
|
|
1546
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
|
1547
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
|
1548
|
+
# [+:foreign_type+]
|
|
1687
1549
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
|
1688
1550
|
# association. By default this is guessed to be the name of the association with a "_type"
|
|
1689
1551
|
# suffix. So a class that defines a <tt>belongs_to :taggable, polymorphic: true</tt>
|
|
1690
1552
|
# association will use "taggable_type" as the default <tt>:foreign_type</tt>.
|
|
1691
|
-
# [
|
|
1553
|
+
# [+:primary_key+]
|
|
1692
1554
|
# Specify the method that returns the primary key of associated object used for the association.
|
|
1693
1555
|
# By default this is +id+.
|
|
1694
|
-
# [
|
|
1556
|
+
# [+:dependent+]
|
|
1695
1557
|
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
|
|
1696
1558
|
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. If set to
|
|
1697
1559
|
# <tt>:destroy_async</tt>, the associated object is scheduled to be destroyed in a background job.
|
|
1698
1560
|
# This option should not be specified when #belongs_to is used in conjunction with
|
|
1699
1561
|
# a #has_many relationship on another class because of the potential to leave
|
|
1700
1562
|
# orphaned records behind.
|
|
1701
|
-
# [
|
|
1563
|
+
# [+:counter_cache+]
|
|
1702
1564
|
# Caches the number of belonging objects on the associate class through the use of CounterCache::ClassMethods#increment_counter
|
|
1703
1565
|
# and CounterCache::ClassMethods#decrement_counter. The counter cache is incremented when an object of this
|
|
1704
1566
|
# class is created and decremented when it's destroyed. This requires that a column
|
|
1705
1567
|
# named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
|
|
1706
1568
|
# is used on the associate class (such as a Post class) - that is the migration for
|
|
1707
1569
|
# <tt>#{table_name}_count</tt> is created on the associate class (such that <tt>Post.comments_count</tt> will
|
|
1708
|
-
# return the count cached
|
|
1570
|
+
# return the count cached). You can also specify a custom counter
|
|
1709
1571
|
# cache column by providing a column name instead of a +true+/+false+ value to this
|
|
1710
1572
|
# option (e.g., <tt>counter_cache: :my_custom_counter</tt>.)
|
|
1711
|
-
#
|
|
1712
|
-
#
|
|
1713
|
-
#
|
|
1714
|
-
#
|
|
1573
|
+
#
|
|
1574
|
+
# Starting to use counter caches on existing large tables can be troublesome, because the column
|
|
1575
|
+
# values must be backfilled separately of the column addition (to not lock the table for too long)
|
|
1576
|
+
# and before the use of +:counter_cache+ (otherwise methods like +size+/+any?+/etc, which use
|
|
1577
|
+
# counter caches internally, can produce incorrect results). To safely backfill the values while keeping
|
|
1578
|
+
# counter cache columns updated with the child records creation/removal and to avoid the mentioned methods
|
|
1579
|
+
# use the possibly incorrect counter cache column values and always get the results from the database,
|
|
1580
|
+
# use <tt>counter_cache: { active: false }</tt>.
|
|
1581
|
+
# If you also need to specify a custom column name, use <tt>counter_cache: { active: false, column: :my_custom_counter }</tt>.
|
|
1582
|
+
#
|
|
1715
1583
|
# Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
|
|
1716
1584
|
# to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
|
|
1717
|
-
# [
|
|
1585
|
+
# [+:polymorphic+]
|
|
1586
|
+
# Specify this association is a polymorphic association by passing +true+.
|
|
1587
|
+
# Note: Since polymorphic associations rely on storing class names in the database, make sure to update the class names in the
|
|
1588
|
+
# <tt>*_type</tt> polymorphic type column of the corresponding rows.
|
|
1589
|
+
# [+:validate+]
|
|
1718
1590
|
# When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
|
|
1719
1591
|
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
|
1720
|
-
# [
|
|
1592
|
+
# [+:autosave+]
|
|
1721
1593
|
# If true, always save the associated object or destroy it if marked for destruction, when
|
|
1722
1594
|
# saving the parent object.
|
|
1723
1595
|
# If false, never save or destroy the associated object.
|
|
@@ -1725,32 +1597,37 @@ module ActiveRecord
|
|
|
1725
1597
|
#
|
|
1726
1598
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for
|
|
1727
1599
|
# sets <tt>:autosave</tt> to <tt>true</tt>.
|
|
1728
|
-
# [
|
|
1729
|
-
# If true, the associated object will be touched (the updated_at/
|
|
1600
|
+
# [+:touch+]
|
|
1601
|
+
# If true, the associated object will be touched (the +updated_at+ / +updated_on+ attributes set to current time)
|
|
1730
1602
|
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
|
1731
|
-
# will be updated with the current time in addition to the updated_at/
|
|
1732
|
-
# Please note that
|
|
1733
|
-
# +after_commit
|
|
1734
|
-
# [
|
|
1603
|
+
# will be updated with the current time in addition to the +updated_at+ / +updated_on+ attribute.
|
|
1604
|
+
# Please note that no validation will be performed when touching, and only the +after_touch+,
|
|
1605
|
+
# +after_commit+, and +after_rollback+ callbacks will be executed.
|
|
1606
|
+
# [+:inverse_of+]
|
|
1735
1607
|
# Specifies the name of the #has_one or #has_many association on the associated
|
|
1736
1608
|
# object that is the inverse of this #belongs_to association.
|
|
1737
1609
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
|
1738
|
-
# [
|
|
1610
|
+
# [+:optional+]
|
|
1739
1611
|
# When set to +true+, the association will not have its presence validated.
|
|
1740
|
-
# [
|
|
1612
|
+
# [+:required+]
|
|
1741
1613
|
# When set to +true+, the association will also have its presence validated.
|
|
1742
1614
|
# This will validate the association itself, not the id. You can use
|
|
1743
1615
|
# +:inverse_of+ to avoid an extra query during validation.
|
|
1744
1616
|
# NOTE: <tt>required</tt> is set to <tt>true</tt> by default and is deprecated. If
|
|
1745
1617
|
# you don't want to have association presence validated, use <tt>optional: true</tt>.
|
|
1746
|
-
# [
|
|
1618
|
+
# [+:default+]
|
|
1747
1619
|
# Provide a callable (i.e. proc or lambda) to specify that the association should
|
|
1748
1620
|
# be initialized with a particular record before validation.
|
|
1749
|
-
#
|
|
1621
|
+
# Please note that callable won't be executed if the record exists.
|
|
1622
|
+
# [+:strict_loading+]
|
|
1750
1623
|
# Enforces strict loading every time the associated record is loaded through this association.
|
|
1751
|
-
# [
|
|
1624
|
+
# [+:ensuring_owner_was+]
|
|
1752
1625
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
|
1753
1626
|
# associated records to be deleted in a background job.
|
|
1627
|
+
# [+:query_constraints+]
|
|
1628
|
+
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
|
1629
|
+
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
|
1630
|
+
# When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
|
|
1754
1631
|
#
|
|
1755
1632
|
# Option examples:
|
|
1756
1633
|
# belongs_to :firm, foreign_key: "client_of"
|
|
@@ -1766,6 +1643,7 @@ module ActiveRecord
|
|
|
1766
1643
|
# belongs_to :user, optional: true
|
|
1767
1644
|
# belongs_to :account, default: -> { company.account }
|
|
1768
1645
|
# belongs_to :account, strict_loading: true
|
|
1646
|
+
# belongs_to :note, query_constraints: [:organization_id, :note_id]
|
|
1769
1647
|
def belongs_to(name, scope = nil, **options)
|
|
1770
1648
|
reflection = Builder::BelongsTo.build(self, name, scope, options)
|
|
1771
1649
|
Reflection.add_reflection self, name, reflection
|
|
@@ -1788,7 +1666,7 @@ module ActiveRecord
|
|
|
1788
1666
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
|
1789
1667
|
# join table with a migration such as this:
|
|
1790
1668
|
#
|
|
1791
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.
|
|
1669
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.2]
|
|
1792
1670
|
# def change
|
|
1793
1671
|
# create_join_table :developers, :projects
|
|
1794
1672
|
# end
|
|
@@ -1803,71 +1681,80 @@ module ActiveRecord
|
|
|
1803
1681
|
# +collection+ is a placeholder for the symbol passed as the +name+ argument, so
|
|
1804
1682
|
# <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.
|
|
1805
1683
|
#
|
|
1806
|
-
# [collection]
|
|
1684
|
+
# [<tt>collection</tt>]
|
|
1807
1685
|
# Returns a Relation of all the associated objects.
|
|
1808
1686
|
# An empty Relation is returned if none are found.
|
|
1809
|
-
# [collection<<(object, ...)]
|
|
1687
|
+
# [<tt>collection<<(object, ...)</tt>]
|
|
1810
1688
|
# Adds one or more objects to the collection by creating associations in the join table
|
|
1811
1689
|
# (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
|
|
1812
1690
|
# Note that this operation instantly fires update SQL without waiting for the save or update call on the
|
|
1813
1691
|
# parent object, unless the parent object is a new record.
|
|
1814
|
-
# [collection.delete(object, ...)]
|
|
1692
|
+
# [<tt>collection.delete(object, ...)</tt>]
|
|
1815
1693
|
# Removes one or more objects from the collection by removing their associations from the join table.
|
|
1816
1694
|
# This does not destroy the objects.
|
|
1817
|
-
# [collection.destroy(object, ...)]
|
|
1695
|
+
# [<tt>collection.destroy(object, ...)</tt>]
|
|
1818
1696
|
# Removes one or more objects from the collection by running destroy on each association in the join table, overriding any dependent option.
|
|
1819
1697
|
# This does not destroy the objects.
|
|
1820
|
-
# [collection=objects]
|
|
1698
|
+
# [<tt>collection=objects</tt>]
|
|
1821
1699
|
# Replaces the collection's content by deleting and adding objects as appropriate.
|
|
1822
|
-
# [collection_singular_ids]
|
|
1700
|
+
# [<tt>collection_singular_ids</tt>]
|
|
1823
1701
|
# Returns an array of the associated objects' ids.
|
|
1824
|
-
# [collection_singular_ids=ids]
|
|
1702
|
+
# [<tt>collection_singular_ids=ids</tt>]
|
|
1825
1703
|
# Replace the collection by the objects identified by the primary keys in +ids+.
|
|
1826
|
-
# [collection.clear]
|
|
1704
|
+
# [<tt>collection.clear</tt>]
|
|
1827
1705
|
# Removes every object from the collection. This does not destroy the objects.
|
|
1828
|
-
# [collection.empty
|
|
1706
|
+
# [<tt>collection.empty?</tt>]
|
|
1829
1707
|
# Returns +true+ if there are no associated objects.
|
|
1830
|
-
# [collection.size]
|
|
1708
|
+
# [<tt>collection.size</tt>]
|
|
1831
1709
|
# Returns the number of associated objects.
|
|
1832
|
-
# [collection.find(id)]
|
|
1710
|
+
# [<tt>collection.find(id)</tt>]
|
|
1833
1711
|
# Finds an associated object responding to the +id+ and that
|
|
1834
1712
|
# meets the condition that it has to be associated with this object.
|
|
1835
1713
|
# Uses the same rules as ActiveRecord::FinderMethods#find.
|
|
1836
|
-
# [collection.exists?(...)]
|
|
1714
|
+
# [<tt>collection.exists?(...)</tt>]
|
|
1837
1715
|
# Checks whether an associated object with the given conditions exists.
|
|
1838
1716
|
# Uses the same rules as ActiveRecord::FinderMethods#exists?.
|
|
1839
|
-
# [collection.build(attributes = {})]
|
|
1717
|
+
# [<tt>collection.build(attributes = {})</tt>]
|
|
1840
1718
|
# Returns a new object of the collection type that has been instantiated
|
|
1841
1719
|
# with +attributes+ and linked to this object through the join table, but has not yet been saved.
|
|
1842
|
-
# [collection.create(attributes = {})]
|
|
1720
|
+
# [<tt>collection.create(attributes = {})</tt>]
|
|
1843
1721
|
# Returns a new object of the collection type that has been instantiated
|
|
1844
1722
|
# with +attributes+, linked to this object through the join table, and that has already been
|
|
1845
1723
|
# saved (if it passed the validation).
|
|
1846
|
-
# [collection.reload]
|
|
1724
|
+
# [<tt>collection.reload</tt>]
|
|
1847
1725
|
# Returns a Relation of all of the associated objects, forcing a database read.
|
|
1848
1726
|
# An empty Relation is returned if none are found.
|
|
1849
1727
|
#
|
|
1850
|
-
#
|
|
1851
|
-
#
|
|
1852
|
-
#
|
|
1853
|
-
#
|
|
1854
|
-
#
|
|
1855
|
-
#
|
|
1856
|
-
#
|
|
1857
|
-
#
|
|
1858
|
-
#
|
|
1859
|
-
#
|
|
1860
|
-
#
|
|
1861
|
-
#
|
|
1862
|
-
#
|
|
1863
|
-
#
|
|
1864
|
-
#
|
|
1865
|
-
#
|
|
1866
|
-
#
|
|
1867
|
-
#
|
|
1728
|
+
# ==== Example
|
|
1729
|
+
#
|
|
1730
|
+
# class Developer < ActiveRecord::Base
|
|
1731
|
+
# has_and_belongs_to_many :projects
|
|
1732
|
+
# end
|
|
1733
|
+
#
|
|
1734
|
+
# Declaring <tt>has_and_belongs_to_many :projects</tt> adds the following methods (and more):
|
|
1735
|
+
#
|
|
1736
|
+
# developer = Developer.find(11)
|
|
1737
|
+
# project = Project.find(9)
|
|
1738
|
+
#
|
|
1739
|
+
# developer.projects
|
|
1740
|
+
# developer.projects << project
|
|
1741
|
+
# developer.projects.delete(project)
|
|
1742
|
+
# developer.projects.destroy(project)
|
|
1743
|
+
# developer.projects = [project]
|
|
1744
|
+
# developer.project_ids
|
|
1745
|
+
# developer.project_ids = [9]
|
|
1746
|
+
# developer.projects.clear
|
|
1747
|
+
# developer.projects.empty?
|
|
1748
|
+
# developer.projects.size
|
|
1749
|
+
# developer.projects.find(9)
|
|
1750
|
+
# developer.projects.exists?(9)
|
|
1751
|
+
# developer.projects.build # similar to Project.new(developer_id: 11)
|
|
1752
|
+
# developer.projects.create # similar to Project.create(developer_id: 11)
|
|
1753
|
+
# developer.projects.reload
|
|
1754
|
+
#
|
|
1868
1755
|
# The declaration may include an +options+ hash to specialize the behavior of the association.
|
|
1869
1756
|
#
|
|
1870
|
-
#
|
|
1757
|
+
# ==== Scopes
|
|
1871
1758
|
#
|
|
1872
1759
|
# You can pass a second argument +scope+ as a callable (i.e. proc or
|
|
1873
1760
|
# lambda) to retrieve a specific set of records or customize the generated
|
|
@@ -1879,11 +1766,11 @@ module ActiveRecord
|
|
|
1879
1766
|
# where("default_category = ?", post.default_category)
|
|
1880
1767
|
# }
|
|
1881
1768
|
#
|
|
1882
|
-
#
|
|
1769
|
+
# ==== Extensions
|
|
1883
1770
|
#
|
|
1884
1771
|
# The +extension+ argument allows you to pass a block into a
|
|
1885
1772
|
# has_and_belongs_to_many association. This is useful for adding new
|
|
1886
|
-
# finders, creators and other factory-type methods to be used as part of
|
|
1773
|
+
# finders, creators, and other factory-type methods to be used as part of
|
|
1887
1774
|
# the association.
|
|
1888
1775
|
#
|
|
1889
1776
|
# Extension examples:
|
|
@@ -1894,33 +1781,33 @@ module ActiveRecord
|
|
|
1894
1781
|
# end
|
|
1895
1782
|
# end
|
|
1896
1783
|
#
|
|
1897
|
-
#
|
|
1784
|
+
# ==== Options
|
|
1898
1785
|
#
|
|
1899
|
-
# [
|
|
1786
|
+
# [+:class_name+]
|
|
1900
1787
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
|
1901
1788
|
# from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the
|
|
1902
1789
|
# Project class, but if the real class name is SuperProject, you'll have to specify it with this option.
|
|
1903
|
-
# [
|
|
1790
|
+
# [+:join_table+]
|
|
1904
1791
|
# Specify the name of the join table if the default based on lexical order isn't what you want.
|
|
1905
1792
|
# <b>WARNING:</b> If you're overwriting the table name of either class, the +table_name+ method
|
|
1906
1793
|
# MUST be declared underneath any #has_and_belongs_to_many declaration in order to work.
|
|
1907
|
-
# [
|
|
1794
|
+
# [+:foreign_key+]
|
|
1908
1795
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
|
1909
1796
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes
|
|
1910
1797
|
# a #has_and_belongs_to_many association to Project will use "person_id" as the
|
|
1911
1798
|
# default <tt>:foreign_key</tt>.
|
|
1912
1799
|
#
|
|
1913
|
-
#
|
|
1914
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
|
1915
|
-
# [
|
|
1800
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
|
1801
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
|
1802
|
+
# [+:association_foreign_key+]
|
|
1916
1803
|
# Specify the foreign key used for the association on the receiving side of the association.
|
|
1917
1804
|
# By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
|
|
1918
1805
|
# So if a Person class makes a #has_and_belongs_to_many association to Project,
|
|
1919
1806
|
# the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
|
|
1920
|
-
# [
|
|
1807
|
+
# [+:validate+]
|
|
1921
1808
|
# When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
|
|
1922
1809
|
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
|
1923
|
-
# [
|
|
1810
|
+
# [+:autosave+]
|
|
1924
1811
|
# If true, always save the associated objects or destroy them if marked for destruction, when
|
|
1925
1812
|
# saving the parent object.
|
|
1926
1813
|
# If false, never save or destroy the associated objects.
|
|
@@ -1928,7 +1815,7 @@ module ActiveRecord
|
|
|
1928
1815
|
#
|
|
1929
1816
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
|
1930
1817
|
# <tt>:autosave</tt> to <tt>true</tt>.
|
|
1931
|
-
# [
|
|
1818
|
+
# [+:strict_loading+]
|
|
1932
1819
|
# Enforces strict loading every time an associated record is loaded through this association.
|
|
1933
1820
|
#
|
|
1934
1821
|
# Option examples:
|
|
@@ -1973,7 +1860,7 @@ module ActiveRecord
|
|
|
1973
1860
|
end
|
|
1974
1861
|
|
|
1975
1862
|
has_many name, scope, **hm_options, &extension
|
|
1976
|
-
_reflections[name
|
|
1863
|
+
_reflections[name].parent_reflection = habtm_reflection
|
|
1977
1864
|
end
|
|
1978
1865
|
end
|
|
1979
1866
|
end
|