activerecord 6.1.6 → 7.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1627 -983
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +50 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +6 -2
- data/lib/active_record/associations/collection_association.rb +35 -31
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +26 -16
- data/lib/active_record/associations/preloader/association.rb +207 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +50 -14
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +439 -305
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +73 -22
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +25 -10
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +10 -13
- data/lib/active_record/attribute_methods.rb +121 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +61 -30
- data/lib/active_record/base.rb +25 -2
- data/lib/active_record/callbacks.rb +18 -34
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -34
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +96 -590
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +77 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +360 -138
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -149
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +285 -156
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +104 -53
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +394 -74
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +509 -247
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +294 -102
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +107 -136
- data/lib/active_record/core.rb +202 -223
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +84 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +61 -15
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -1
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +224 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +151 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +53 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +92 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +96 -0
- data/lib/active_record/encryption.rb +56 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +171 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +131 -86
- data/lib/active_record/future_result.rb +164 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +135 -22
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +119 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +36 -21
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +112 -14
- data/lib/active_record/migration/compatibility.rb +221 -48
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +358 -171
- data/lib/active_record/model_schema.rb +120 -101
- data/lib/active_record/nested_attributes.rb +37 -18
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +405 -85
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +219 -43
- data/lib/active_record/railties/controller_runtime.rb +13 -9
- data/lib/active_record/railties/databases.rake +188 -252
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +241 -80
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +219 -90
- data/lib/active_record/relation/delegation.rb +27 -13
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +654 -127
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +262 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +18 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +10 -8
- data/lib/active_record/store.rb +16 -11
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +225 -136
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +123 -99
- data/lib/active_record/timestamp.rb +29 -18
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -5
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/and.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +139 -19
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +93 -13
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -1,11 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/enumerable"
|
4
|
-
require "active_support/core_ext/string/conversions"
|
5
|
-
|
6
3
|
module ActiveRecord
|
7
|
-
class AssociationNotFoundError < ConfigurationError
|
4
|
+
class AssociationNotFoundError < ConfigurationError # :nodoc:
|
8
5
|
attr_reader :record, :association_name
|
6
|
+
|
9
7
|
def initialize(record = nil, association_name = nil)
|
10
8
|
@record = record
|
11
9
|
@association_name = association_name
|
@@ -16,32 +14,25 @@ module ActiveRecord
|
|
16
14
|
end
|
17
15
|
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
@error = error
|
22
|
-
end
|
17
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
18
|
+
include DidYouMean::Correctable
|
23
19
|
|
24
20
|
def corrections
|
25
|
-
if
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
}.reverse.first(4)
|
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
|
31
26
|
else
|
32
27
|
[]
|
33
28
|
end
|
34
29
|
end
|
35
30
|
end
|
36
|
-
|
37
|
-
# We may not have DYM, and DYM might not let us register error handlers
|
38
|
-
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
39
|
-
DidYouMean.correct_error(self, Correction)
|
40
|
-
end
|
41
31
|
end
|
42
32
|
|
43
|
-
class InverseOfAssociationNotFoundError < ActiveRecordError
|
33
|
+
class InverseOfAssociationNotFoundError < ActiveRecordError # :nodoc:
|
44
34
|
attr_reader :reflection, :associated_class
|
35
|
+
|
45
36
|
def initialize(reflection = nil, associated_class = nil)
|
46
37
|
if reflection
|
47
38
|
@reflection = reflection
|
@@ -52,31 +43,35 @@ module ActiveRecord
|
|
52
43
|
end
|
53
44
|
end
|
54
45
|
|
55
|
-
|
56
|
-
|
57
|
-
@error = error
|
58
|
-
end
|
46
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
47
|
+
include DidYouMean::Correctable
|
59
48
|
|
60
49
|
def corrections
|
61
|
-
if
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
}.reverse.first(4)
|
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
|
67
55
|
else
|
68
56
|
[]
|
69
57
|
end
|
70
58
|
end
|
71
59
|
end
|
60
|
+
end
|
72
61
|
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
76
71
|
end
|
77
72
|
end
|
78
73
|
|
79
|
-
class HasManyThroughAssociationNotFoundError < ActiveRecordError
|
74
|
+
class HasManyThroughAssociationNotFoundError < ActiveRecordError # :nodoc:
|
80
75
|
attr_reader :owner_class, :reflection
|
81
76
|
|
82
77
|
def initialize(owner_class = nil, reflection = nil)
|
@@ -89,32 +84,24 @@ module ActiveRecord
|
|
89
84
|
end
|
90
85
|
end
|
91
86
|
|
92
|
-
|
93
|
-
|
94
|
-
@error = error
|
95
|
-
end
|
87
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
88
|
+
include DidYouMean::Correctable
|
96
89
|
|
97
90
|
def corrections
|
98
|
-
if
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
}.reverse.first(4)
|
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
|
105
97
|
else
|
106
98
|
[]
|
107
99
|
end
|
108
100
|
end
|
109
101
|
end
|
110
|
-
|
111
|
-
# We may not have DYM, and DYM might not let us register error handlers
|
112
|
-
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
113
|
-
DidYouMean.correct_error(self, Correction)
|
114
|
-
end
|
115
102
|
end
|
116
103
|
|
117
|
-
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError
|
104
|
+
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError # :nodoc:
|
118
105
|
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
119
106
|
if owner_class_name && reflection && source_reflection
|
120
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.")
|
@@ -124,7 +111,7 @@ module ActiveRecord
|
|
124
111
|
end
|
125
112
|
end
|
126
113
|
|
127
|
-
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError
|
114
|
+
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
128
115
|
def initialize(owner_class_name = nil, reflection = nil)
|
129
116
|
if owner_class_name && reflection
|
130
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}'.")
|
@@ -134,7 +121,7 @@ module ActiveRecord
|
|
134
121
|
end
|
135
122
|
end
|
136
123
|
|
137
|
-
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError
|
124
|
+
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError # :nodoc:
|
138
125
|
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
139
126
|
if owner_class_name && reflection && source_reflection
|
140
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.")
|
@@ -144,7 +131,7 @@ module ActiveRecord
|
|
144
131
|
end
|
145
132
|
end
|
146
133
|
|
147
|
-
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError
|
134
|
+
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError # :nodoc:
|
148
135
|
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
149
136
|
if owner_class_name && reflection && through_reflection
|
150
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.")
|
@@ -154,7 +141,7 @@ module ActiveRecord
|
|
154
141
|
end
|
155
142
|
end
|
156
143
|
|
157
|
-
class HasOneAssociationPolymorphicThroughError < ActiveRecordError
|
144
|
+
class HasOneAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
|
158
145
|
def initialize(owner_class_name = nil, reflection = nil)
|
159
146
|
if owner_class_name && reflection
|
160
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}'.")
|
@@ -164,7 +151,7 @@ module ActiveRecord
|
|
164
151
|
end
|
165
152
|
end
|
166
153
|
|
167
|
-
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError
|
154
|
+
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError # :nodoc:
|
168
155
|
def initialize(reflection = nil)
|
169
156
|
if reflection
|
170
157
|
through_reflection = reflection.through_reflection
|
@@ -177,7 +164,7 @@ module ActiveRecord
|
|
177
164
|
end
|
178
165
|
end
|
179
166
|
|
180
|
-
class HasManyThroughOrderError < ActiveRecordError
|
167
|
+
class HasManyThroughOrderError < ActiveRecordError # :nodoc:
|
181
168
|
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
182
169
|
if owner_class_name && reflection && through_reflection
|
183
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.")
|
@@ -187,7 +174,7 @@ module ActiveRecord
|
|
187
174
|
end
|
188
175
|
end
|
189
176
|
|
190
|
-
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError
|
177
|
+
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError # :nodoc:
|
191
178
|
def initialize(owner = nil, reflection = nil)
|
192
179
|
if owner && reflection
|
193
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}.")
|
@@ -197,6 +184,22 @@ module ActiveRecord
|
|
197
184
|
end
|
198
185
|
end
|
199
186
|
|
187
|
+
class CompositePrimaryKeyMismatchError < ActiveRecordError # :nodoc:
|
188
|
+
attr_reader :reflection
|
189
|
+
|
190
|
+
def initialize(reflection = nil)
|
191
|
+
if reflection
|
192
|
+
if reflection.has_one? || reflection.collection?
|
193
|
+
super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.active_record_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
|
194
|
+
else
|
195
|
+
super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.association_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
|
196
|
+
end
|
197
|
+
else
|
198
|
+
super("Association primary key doesn't match with foreign key.")
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
200
203
|
class AmbiguousSourceReflectionForThroughAssociation < ActiveRecordError # :nodoc:
|
201
204
|
def initialize(klass, macro, association_name, options, possible_sources)
|
202
205
|
example_options = options.dup
|
@@ -212,13 +215,13 @@ module ActiveRecord
|
|
212
215
|
end
|
213
216
|
end
|
214
217
|
|
215
|
-
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection
|
218
|
+
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
216
219
|
end
|
217
220
|
|
218
|
-
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection
|
221
|
+
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
|
219
222
|
end
|
220
223
|
|
221
|
-
class ThroughNestedAssociationsAreReadonly < ActiveRecordError
|
224
|
+
class ThroughNestedAssociationsAreReadonly < ActiveRecordError # :nodoc:
|
222
225
|
def initialize(owner = nil, reflection = nil)
|
223
226
|
if owner && reflection
|
224
227
|
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
|
@@ -228,10 +231,10 @@ module ActiveRecord
|
|
228
231
|
end
|
229
232
|
end
|
230
233
|
|
231
|
-
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly
|
234
|
+
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
232
235
|
end
|
233
236
|
|
234
|
-
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly
|
237
|
+
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
|
235
238
|
end
|
236
239
|
|
237
240
|
# This error is raised when trying to eager load a polymorphic association using a JOIN.
|
@@ -250,7 +253,7 @@ module ActiveRecord
|
|
250
253
|
# This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
|
251
254
|
# (has_many, has_one) when there is at least 1 child associated instance.
|
252
255
|
# ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
|
253
|
-
class DeleteRestrictionError < ActiveRecordError
|
256
|
+
class DeleteRestrictionError < ActiveRecordError # :nodoc:
|
254
257
|
def initialize(name = nil)
|
255
258
|
if name
|
256
259
|
super("Cannot delete record because of dependent #{name}")
|
@@ -274,7 +277,7 @@ module ActiveRecord
|
|
274
277
|
autoload :CollectionProxy
|
275
278
|
autoload :ThroughAssociation
|
276
279
|
|
277
|
-
module Builder
|
280
|
+
module Builder # :nodoc:
|
278
281
|
autoload :Association, "active_record/associations/builder/association"
|
279
282
|
autoload :SingularAssociation, "active_record/associations/builder/singular_association"
|
280
283
|
autoload :CollectionAssociation, "active_record/associations/builder/collection_association"
|
@@ -296,16 +299,18 @@ module ActiveRecord
|
|
296
299
|
autoload :Preloader
|
297
300
|
autoload :JoinDependency
|
298
301
|
autoload :AssociationScope
|
302
|
+
autoload :DisableJoinsAssociationScope
|
299
303
|
autoload :AliasTracker
|
300
304
|
end
|
301
305
|
|
302
306
|
def self.eager_load!
|
303
307
|
super
|
304
308
|
Preloader.eager_load!
|
309
|
+
JoinDependency.eager_load!
|
305
310
|
end
|
306
311
|
|
307
312
|
# Returns the association instance for the given name, instantiating it if it doesn't already exist
|
308
|
-
def association(name)
|
313
|
+
def association(name) # :nodoc:
|
309
314
|
association = association_instance_get(name)
|
310
315
|
|
311
316
|
if association.nil?
|
@@ -328,20 +333,10 @@ module ActiveRecord
|
|
328
333
|
super
|
329
334
|
end
|
330
335
|
|
331
|
-
def reload(*) # :nodoc:
|
332
|
-
clear_association_cache
|
333
|
-
super
|
334
|
-
end
|
335
|
-
|
336
336
|
private
|
337
|
-
# Clears out the association cache.
|
338
|
-
def clear_association_cache
|
339
|
-
@association_cache.clear if persisted?
|
340
|
-
end
|
341
|
-
|
342
337
|
def init_internals
|
343
|
-
@association_cache = {}
|
344
338
|
super
|
339
|
+
@association_cache = {}
|
345
340
|
end
|
346
341
|
|
347
342
|
# Returns the specified association instance if it exists, +nil+ otherwise.
|
@@ -354,6 +349,8 @@ module ActiveRecord
|
|
354
349
|
@association_cache[name] = association
|
355
350
|
end
|
356
351
|
|
352
|
+
# = Active Record \Associations
|
353
|
+
#
|
357
354
|
# \Associations are a set of macro-like class methods for tying objects together through
|
358
355
|
# foreign keys. They express relationships like "Project has one Project Manager"
|
359
356
|
# or "Project belongs to a Portfolio". Each macro adds a number of methods to the
|
@@ -370,23 +367,42 @@ module ActiveRecord
|
|
370
367
|
#
|
371
368
|
# The project class now has the following methods (and more) to ease the traversal and
|
372
369
|
# manipulation of its relationships:
|
373
|
-
#
|
374
|
-
#
|
375
|
-
#
|
376
|
-
#
|
377
|
-
#
|
378
|
-
#
|
379
|
-
#
|
370
|
+
#
|
371
|
+
# project = Project.first
|
372
|
+
# project.portfolio
|
373
|
+
# project.portfolio = Portfolio.first
|
374
|
+
# project.reload_portfolio
|
375
|
+
#
|
376
|
+
# project.project_manager
|
377
|
+
# project.project_manager = ProjectManager.first
|
378
|
+
# project.reload_project_manager
|
379
|
+
#
|
380
|
+
# project.milestones.empty?
|
381
|
+
# project.milestones.size
|
382
|
+
# project.milestones
|
383
|
+
# project.milestones << Milestone.first
|
384
|
+
# project.milestones.delete(Milestone.first)
|
385
|
+
# project.milestones.destroy(Milestone.first)
|
386
|
+
# project.milestones.find(Milestone.first.id)
|
387
|
+
# project.milestones.build
|
388
|
+
# project.milestones.create
|
389
|
+
#
|
390
|
+
# project.categories.empty?
|
391
|
+
# project.categories.size
|
392
|
+
# project.categories
|
393
|
+
# project.categories << Category.first
|
394
|
+
# project.categories.delete(category1)
|
395
|
+
# project.categories.destroy(category1)
|
380
396
|
#
|
381
397
|
# === A word of warning
|
382
398
|
#
|
383
399
|
# Don't create associations that have the same name as {instance methods}[rdoc-ref:ActiveRecord::Core] of
|
384
|
-
#
|
385
|
-
# its model, using an association with the same name as one provided by
|
386
|
-
# For instance, +attributes+ and +connection+ would be bad choices for association names, because those names already exist in the list of
|
400
|
+
# +ActiveRecord::Base+. Since the association adds a method with that name to
|
401
|
+
# its model, using an association with the same name as one provided by +ActiveRecord::Base+ will override the method inherited through +ActiveRecord::Base+ and will break things.
|
402
|
+
# For instance, +attributes+ and +connection+ would be bad choices for association names, because those names already exist in the list of +ActiveRecord::Base+ instance methods.
|
387
403
|
#
|
388
404
|
# == Auto-generated methods
|
389
|
-
# See also Instance Public methods below for more details.
|
405
|
+
# See also "Instance Public methods" below ( from #belongs_to ) for more details.
|
390
406
|
#
|
391
407
|
# === Singular associations (one-to-one)
|
392
408
|
# | | belongs_to |
|
@@ -398,6 +414,8 @@ module ActiveRecord
|
|
398
414
|
# create_other(attributes={}) | X | | X
|
399
415
|
# create_other!(attributes={}) | X | | X
|
400
416
|
# reload_other | X | X | X
|
417
|
+
# other_changed? | X | X |
|
418
|
+
# other_previously_changed? | X | X |
|
401
419
|
#
|
402
420
|
# === Collection associations (one-to-many / many-to-many)
|
403
421
|
# | | | has_many
|
@@ -451,7 +469,7 @@ module ActiveRecord
|
|
451
469
|
#
|
452
470
|
# == Cardinality and associations
|
453
471
|
#
|
454
|
-
# Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
|
472
|
+
# Active Record associations can be used to describe one-to-one, one-to-many, and many-to-many
|
455
473
|
# relationships between models. Each model uses an association to describe its role in
|
456
474
|
# the relation. The #belongs_to association is always used in the model that has
|
457
475
|
# the foreign key.
|
@@ -605,8 +623,11 @@ module ActiveRecord
|
|
605
623
|
# has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
|
606
624
|
# end
|
607
625
|
#
|
608
|
-
# Note: Joining
|
609
|
-
#
|
626
|
+
# Note: Joining or eager loading such associations is not possible because
|
627
|
+
# those operations happen before instance creation. Such associations
|
628
|
+
# _can_ be preloaded, but doing so will perform N+1 queries because there
|
629
|
+
# will be a different scope for each record (similar to preloading
|
630
|
+
# polymorphic scopes).
|
610
631
|
#
|
611
632
|
# == Association callbacks
|
612
633
|
#
|
@@ -614,22 +635,31 @@ module ActiveRecord
|
|
614
635
|
# you can also define callbacks that get triggered when you add an object to or remove an
|
615
636
|
# object from an association collection.
|
616
637
|
#
|
617
|
-
# class
|
618
|
-
#
|
638
|
+
# class Firm < ActiveRecord::Base
|
639
|
+
# has_many :clients,
|
640
|
+
# dependent: :destroy,
|
641
|
+
# after_add: :congratulate_client,
|
642
|
+
# after_remove: :log_after_remove
|
643
|
+
#
|
644
|
+
# def congratulate_client(record)
|
645
|
+
# # ...
|
646
|
+
# end
|
619
647
|
#
|
620
|
-
# def
|
621
|
-
# ...
|
648
|
+
# def log_after_remove(record)
|
649
|
+
# # ...
|
622
650
|
# end
|
623
651
|
# end
|
624
652
|
#
|
625
653
|
# It's possible to stack callbacks by passing them as an array. Example:
|
626
654
|
#
|
627
|
-
# class
|
628
|
-
#
|
629
|
-
#
|
655
|
+
# class Firm < ActiveRecord::Base
|
656
|
+
# has_many :clients,
|
657
|
+
# dependent: :destroy,
|
658
|
+
# after_add: [:congratulate_client, -> (firm, record) { firm.log << "after_adding#{record.id}" }],
|
659
|
+
# after_remove: :log_after_remove
|
630
660
|
# end
|
631
661
|
#
|
632
|
-
# Possible callbacks are: +before_add+, +after_add+, +before_remove
|
662
|
+
# Possible callbacks are: +before_add+, +after_add+, +before_remove+, and +after_remove+.
|
633
663
|
#
|
634
664
|
# If any of the +before_add+ callbacks throw an exception, the object will not be
|
635
665
|
# added to the collection.
|
@@ -637,6 +667,18 @@ module ActiveRecord
|
|
637
667
|
# Similarly, if any of the +before_remove+ callbacks throw an exception, the object
|
638
668
|
# will not be removed from the collection.
|
639
669
|
#
|
670
|
+
# Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example:
|
671
|
+
#
|
672
|
+
# * <tt>firm.clients.destroy(client)</tt>
|
673
|
+
# * <tt>firm.clients.destroy(*clients)</tt>
|
674
|
+
# * <tt>firm.clients.destroy_all</tt>
|
675
|
+
#
|
676
|
+
# +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks:
|
677
|
+
#
|
678
|
+
# * <tt>firm.clients.delete(client)</tt>
|
679
|
+
# * <tt>firm.clients.delete(*clients)</tt>
|
680
|
+
# * <tt>firm.clients.delete_all</tt>
|
681
|
+
#
|
640
682
|
# == Association extensions
|
641
683
|
#
|
642
684
|
# The proxy objects that control the access to associations can be extended through anonymous
|
@@ -780,9 +822,10 @@ module ActiveRecord
|
|
780
822
|
# inverse detection only works on #has_many, #has_one, and
|
781
823
|
# #belongs_to associations.
|
782
824
|
#
|
783
|
-
# <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations
|
784
|
-
#
|
785
|
-
#
|
825
|
+
# <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations
|
826
|
+
# will also prevent the association's inverse from being found automatically,
|
827
|
+
# as will a custom scopes in some cases. See further details in the
|
828
|
+
# {Active Record Associations guide}[https://guides.rubyonrails.org/association_basics.html#bi-directional-associations].
|
786
829
|
#
|
787
830
|
# The automatic guessing of the inverse association uses a heuristic based
|
788
831
|
# on the name of the class, so it may not work for all associations,
|
@@ -1020,45 +1063,45 @@ module ActiveRecord
|
|
1020
1063
|
# Indexes are appended for any more successive uses of the table name.
|
1021
1064
|
#
|
1022
1065
|
# Post.joins(:comments)
|
1023
|
-
# #
|
1066
|
+
# # SELECT ... FROM posts INNER JOIN comments ON ...
|
1024
1067
|
# Post.joins(:special_comments) # STI
|
1025
|
-
# #
|
1068
|
+
# # SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
|
1026
1069
|
# Post.joins(:comments, :special_comments) # special_comments is the reflection name, posts is the parent table name
|
1027
|
-
# #
|
1070
|
+
# # SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
|
1028
1071
|
#
|
1029
1072
|
# Acts as tree example:
|
1030
1073
|
#
|
1031
1074
|
# TreeMixin.joins(:children)
|
1032
|
-
# #
|
1075
|
+
# # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
1033
1076
|
# TreeMixin.joins(children: :parent)
|
1034
|
-
# #
|
1035
|
-
#
|
1077
|
+
# # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
1078
|
+
# # INNER JOIN parents_mixins ...
|
1036
1079
|
# TreeMixin.joins(children: {parent: :children})
|
1037
|
-
# #
|
1038
|
-
#
|
1039
|
-
#
|
1080
|
+
# # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
|
1081
|
+
# # INNER JOIN parents_mixins ...
|
1082
|
+
# # INNER JOIN mixins childrens_mixins_2
|
1040
1083
|
#
|
1041
1084
|
# Has and Belongs to Many join tables use the same idea, but add a <tt>_join</tt> suffix:
|
1042
1085
|
#
|
1043
1086
|
# Post.joins(:categories)
|
1044
|
-
# #
|
1087
|
+
# # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
1045
1088
|
# Post.joins(categories: :posts)
|
1046
|
-
# #
|
1047
|
-
#
|
1089
|
+
# # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
1090
|
+
# # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
1048
1091
|
# Post.joins(categories: {posts: :categories})
|
1049
|
-
# #
|
1050
|
-
#
|
1051
|
-
#
|
1092
|
+
# # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
|
1093
|
+
# # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
1094
|
+
# # INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
|
1052
1095
|
#
|
1053
1096
|
# If you wish to specify your own custom joins using ActiveRecord::QueryMethods#joins method, those table
|
1054
1097
|
# names will take precedence over the eager associations:
|
1055
1098
|
#
|
1056
1099
|
# Post.joins(:comments).joins("inner join comments ...")
|
1057
|
-
# #
|
1100
|
+
# # SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
|
1058
1101
|
# Post.joins(:comments, :special_comments).joins("inner join comments ...")
|
1059
|
-
# #
|
1060
|
-
#
|
1061
|
-
#
|
1102
|
+
# # SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
|
1103
|
+
# # INNER JOIN comments special_comments_posts ...
|
1104
|
+
# # INNER JOIN comments ...
|
1062
1105
|
#
|
1063
1106
|
# Table aliases are automatically truncated according to the maximum length of table identifiers
|
1064
1107
|
# according to the specific database.
|
@@ -1139,7 +1182,8 @@ module ActiveRecord
|
|
1139
1182
|
# belongs_to :dungeon, inverse_of: :evil_wizard
|
1140
1183
|
# end
|
1141
1184
|
#
|
1142
|
-
# For more information, see the documentation for the +:inverse_of+ option
|
1185
|
+
# For more information, see the documentation for the +:inverse_of+ option and the
|
1186
|
+
# {Active Record Associations guide}[https://guides.rubyonrails.org/association_basics.html#bi-directional-associations].
|
1143
1187
|
#
|
1144
1188
|
# == Deleting from associations
|
1145
1189
|
#
|
@@ -1161,7 +1205,7 @@ module ActiveRecord
|
|
1161
1205
|
# specific association types. When no option is given, the behavior is to do nothing
|
1162
1206
|
# with the associated records when destroying a record.
|
1163
1207
|
#
|
1164
|
-
# Note that <tt>:dependent</tt> is implemented using Rails' callback
|
1208
|
+
# Note that <tt>:dependent</tt> is implemented using \Rails' callback
|
1165
1209
|
# system, which works by processing callbacks in order. Therefore, other
|
1166
1210
|
# callbacks declared either before or after the <tt>:dependent</tt> option
|
1167
1211
|
# can affect what it does.
|
@@ -1232,15 +1276,15 @@ module ActiveRecord
|
|
1232
1276
|
# +collection+ is a placeholder for the symbol passed as the +name+ argument, so
|
1233
1277
|
# <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
|
1234
1278
|
#
|
1235
|
-
# [collection]
|
1279
|
+
# [<tt>collection</tt>]
|
1236
1280
|
# Returns a Relation of all the associated objects.
|
1237
1281
|
# An empty Relation is returned if none are found.
|
1238
|
-
# [collection<<(object, ...)]
|
1282
|
+
# [<tt>collection<<(object, ...)</tt>]
|
1239
1283
|
# Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
|
1240
1284
|
# Note that this operation instantly fires update SQL without waiting for the save or update call on the
|
1241
1285
|
# parent object, unless the parent object is a new record.
|
1242
1286
|
# This will also run validations and callbacks of associated object(s).
|
1243
|
-
# [collection.delete(object, ...)]
|
1287
|
+
# [<tt>collection.delete(object, ...)</tt>]
|
1244
1288
|
# Removes one or more objects from the collection by setting their foreign keys to +NULL+.
|
1245
1289
|
# Objects will be in addition destroyed if they're associated with <tt>dependent: :destroy</tt>,
|
1246
1290
|
# and deleted if they're associated with <tt>dependent: :delete_all</tt>.
|
@@ -1248,75 +1292,84 @@ module ActiveRecord
|
|
1248
1292
|
# If the <tt>:through</tt> option is used, then the join records are deleted (rather than
|
1249
1293
|
# nullified) by default, but you can specify <tt>dependent: :destroy</tt> or
|
1250
1294
|
# <tt>dependent: :nullify</tt> to override this.
|
1251
|
-
# [collection.destroy(object, ...)]
|
1295
|
+
# [<tt>collection.destroy(object, ...)</tt>]
|
1252
1296
|
# Removes one or more objects from the collection by running <tt>destroy</tt> on
|
1253
1297
|
# each record, regardless of any dependent option, ensuring callbacks are run.
|
1254
1298
|
#
|
1255
1299
|
# If the <tt>:through</tt> option is used, then the join records are destroyed
|
1256
1300
|
# instead, not the objects themselves.
|
1257
|
-
# [collection=objects]
|
1301
|
+
# [<tt>collection=objects</tt>]
|
1258
1302
|
# Replaces the collections content by deleting and adding objects as appropriate. If the <tt>:through</tt>
|
1259
1303
|
# option is true callbacks in the join models are triggered except destroy callbacks, since deletion is
|
1260
1304
|
# direct by default. You can specify <tt>dependent: :destroy</tt> or
|
1261
1305
|
# <tt>dependent: :nullify</tt> to override this.
|
1262
|
-
# [collection_singular_ids]
|
1306
|
+
# [<tt>collection_singular_ids</tt>]
|
1263
1307
|
# Returns an array of the associated objects' ids
|
1264
|
-
# [collection_singular_ids=ids]
|
1308
|
+
# [<tt>collection_singular_ids=ids</tt>]
|
1265
1309
|
# Replace the collection with the objects identified by the primary keys in +ids+. This
|
1266
1310
|
# method loads the models and calls <tt>collection=</tt>. See above.
|
1267
|
-
# [collection.clear]
|
1311
|
+
# [<tt>collection.clear</tt>]
|
1268
1312
|
# Removes every object from the collection. This destroys the associated objects if they
|
1269
1313
|
# are associated with <tt>dependent: :destroy</tt>, deletes them directly from the
|
1270
1314
|
# database if <tt>dependent: :delete_all</tt>, otherwise sets their foreign keys to +NULL+.
|
1271
1315
|
# If the <tt>:through</tt> option is true no destroy callbacks are invoked on the join models.
|
1272
1316
|
# Join models are directly deleted.
|
1273
|
-
# [collection.empty
|
1317
|
+
# [<tt>collection.empty?</tt>]
|
1274
1318
|
# Returns +true+ if there are no associated objects.
|
1275
|
-
# [collection.size]
|
1319
|
+
# [<tt>collection.size</tt>]
|
1276
1320
|
# Returns the number of associated objects.
|
1277
|
-
# [collection.find(...)]
|
1321
|
+
# [<tt>collection.find(...)</tt>]
|
1278
1322
|
# Finds an associated object according to the same rules as ActiveRecord::FinderMethods#find.
|
1279
|
-
# [collection.exists?(...)]
|
1323
|
+
# [<tt>collection.exists?(...)</tt>]
|
1280
1324
|
# Checks whether an associated object with the given conditions exists.
|
1281
1325
|
# Uses the same rules as ActiveRecord::FinderMethods#exists?.
|
1282
|
-
# [collection.build(attributes = {}, ...)]
|
1326
|
+
# [<tt>collection.build(attributes = {}, ...)</tt>]
|
1283
1327
|
# Returns one or more new objects of the collection type that have been instantiated
|
1284
1328
|
# with +attributes+ and linked to this object through a foreign key, but have not yet
|
1285
1329
|
# been saved.
|
1286
|
-
# [collection.create(attributes = {})]
|
1330
|
+
# [<tt>collection.create(attributes = {})</tt>]
|
1287
1331
|
# Returns a new object of the collection type that has been instantiated
|
1288
1332
|
# with +attributes+, linked to this object through a foreign key, and that has already
|
1289
1333
|
# been saved (if it passed the validation). *Note*: This only works if the base model
|
1290
1334
|
# already exists in the DB, not if it is a new (unsaved) record!
|
1291
|
-
# [collection.create!(attributes = {})]
|
1335
|
+
# [<tt>collection.create!(attributes = {})</tt>]
|
1292
1336
|
# Does the same as <tt>collection.create</tt>, but raises ActiveRecord::RecordInvalid
|
1293
1337
|
# if the record is invalid.
|
1294
|
-
# [collection.reload]
|
1338
|
+
# [<tt>collection.reload</tt>]
|
1295
1339
|
# Returns a Relation of all of the associated objects, forcing a database read.
|
1296
1340
|
# An empty Relation is returned if none are found.
|
1297
1341
|
#
|
1298
|
-
#
|
1299
|
-
#
|
1300
|
-
#
|
1301
|
-
#
|
1302
|
-
#
|
1303
|
-
#
|
1304
|
-
#
|
1305
|
-
#
|
1306
|
-
#
|
1307
|
-
#
|
1308
|
-
#
|
1309
|
-
#
|
1310
|
-
#
|
1311
|
-
#
|
1312
|
-
#
|
1313
|
-
#
|
1314
|
-
#
|
1315
|
-
#
|
1316
|
-
#
|
1342
|
+
# ==== Example
|
1343
|
+
#
|
1344
|
+
# class Firm < ActiveRecord::Base
|
1345
|
+
# has_many :clients
|
1346
|
+
# end
|
1347
|
+
#
|
1348
|
+
# Declaring <tt>has_many :clients</tt> adds the following methods (and more):
|
1349
|
+
#
|
1350
|
+
# firm = Firm.find(2)
|
1351
|
+
# client = Client.find(6)
|
1352
|
+
#
|
1353
|
+
# firm.clients # similar to Client.where(firm_id: 2)
|
1354
|
+
# firm.clients << client
|
1355
|
+
# firm.clients.delete(client)
|
1356
|
+
# firm.clients.destroy(client)
|
1357
|
+
# firm.clients = [client]
|
1358
|
+
# firm.client_ids
|
1359
|
+
# firm.client_ids = [6]
|
1360
|
+
# firm.clients.clear
|
1361
|
+
# firm.clients.empty? # similar to firm.clients.size == 0
|
1362
|
+
# firm.clients.size # similar to Client.count "firm_id = 2"
|
1363
|
+
# firm.clients.find # similar to Client.where(firm_id: 2).find(6)
|
1364
|
+
# firm.clients.exists?(name: 'ACME') # similar to Client.exists?(name: 'ACME', firm_id: 2)
|
1365
|
+
# firm.clients.build # similar to Client.new(firm_id: 2)
|
1366
|
+
# firm.clients.create # similar to Client.create(firm_id: 2)
|
1367
|
+
# firm.clients.create! # similar to Client.create!(firm_id: 2)
|
1368
|
+
# firm.clients.reload
|
1369
|
+
#
|
1317
1370
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1318
1371
|
#
|
1319
|
-
#
|
1372
|
+
# ==== Scopes
|
1320
1373
|
#
|
1321
1374
|
# You can pass a second argument +scope+ as a callable (i.e. proc or
|
1322
1375
|
# lambda) to retrieve a specific set of records or customize the generated
|
@@ -1327,10 +1380,10 @@ module ActiveRecord
|
|
1327
1380
|
# has_many :employees, -> { joins(:address) }
|
1328
1381
|
# has_many :posts, ->(blog) { where("max_post_length > ?", blog.max_post_length) }
|
1329
1382
|
#
|
1330
|
-
#
|
1383
|
+
# ==== Extensions
|
1331
1384
|
#
|
1332
1385
|
# The +extension+ argument allows you to pass a block into a has_many
|
1333
|
-
# association. This is useful for adding new finders, creators and other
|
1386
|
+
# association. This is useful for adding new finders, creators, and other
|
1334
1387
|
# factory-type methods to be used as part of the association.
|
1335
1388
|
#
|
1336
1389
|
# Extension examples:
|
@@ -1341,31 +1394,31 @@ module ActiveRecord
|
|
1341
1394
|
# end
|
1342
1395
|
# end
|
1343
1396
|
#
|
1344
|
-
#
|
1345
|
-
# [
|
1397
|
+
# ==== Options
|
1398
|
+
# [+:class_name+]
|
1346
1399
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
1347
1400
|
# from the association name. So <tt>has_many :products</tt> will by default be linked
|
1348
1401
|
# to the +Product+ class, but if the real class name is +SpecialProduct+, you'll have to
|
1349
1402
|
# specify it with this option.
|
1350
|
-
# [
|
1403
|
+
# [+:foreign_key+]
|
1351
1404
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1352
1405
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_many
|
1353
1406
|
# association will use "person_id" as the default <tt>:foreign_key</tt>.
|
1354
1407
|
#
|
1355
|
-
#
|
1356
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
1357
|
-
# [
|
1408
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
1409
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
1410
|
+
# [+:foreign_type+]
|
1358
1411
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
1359
1412
|
# association. By default this is guessed to be the name of the polymorphic association
|
1360
1413
|
# specified on "as" option with a "_type" suffix. So a class that defines a
|
1361
1414
|
# <tt>has_many :tags, as: :taggable</tt> association will use "taggable_type" as the
|
1362
1415
|
# default <tt>:foreign_type</tt>.
|
1363
|
-
# [
|
1416
|
+
# [+:primary_key+]
|
1364
1417
|
# Specify the name of the column to use as the primary key for the association. By default this is +id+.
|
1365
|
-
# [
|
1418
|
+
# [+:dependent+]
|
1366
1419
|
# Controls what happens to the associated objects when
|
1367
1420
|
# their owner is destroyed. Note that these are implemented as
|
1368
|
-
# callbacks, and Rails executes callbacks in order. Therefore, other
|
1421
|
+
# callbacks, and \Rails executes callbacks in order. Therefore, other
|
1369
1422
|
# similar callbacks may affect the <tt>:dependent</tt> behavior, and the
|
1370
1423
|
# <tt>:dependent</tt> behavior may affect other callbacks.
|
1371
1424
|
#
|
@@ -1377,7 +1430,7 @@ module ActiveRecord
|
|
1377
1430
|
# * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
|
1378
1431
|
# * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Polymorphic type will also be nullified
|
1379
1432
|
# on polymorphic associations. Callbacks are not executed.
|
1380
|
-
# * <tt>:restrict_with_exception</tt> causes an
|
1433
|
+
# * <tt>:restrict_with_exception</tt> causes an ActiveRecord::DeleteRestrictionError exception to be raised if there are any associated records.
|
1381
1434
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
|
1382
1435
|
#
|
1383
1436
|
# If using with the <tt>:through</tt> option, the association on the join model must be
|
@@ -1389,12 +1442,12 @@ module ActiveRecord
|
|
1389
1442
|
# <tt>has_many :comments, -> { where published: true }, dependent: :destroy</tt> and <tt>destroy</tt> is
|
1390
1443
|
# called on a post, only published comments are destroyed. This means that any unpublished comments in the
|
1391
1444
|
# database would still contain a foreign key pointing to the now deleted post.
|
1392
|
-
# [
|
1445
|
+
# [+:counter_cache+]
|
1393
1446
|
# This option can be used to configure a custom named <tt>:counter_cache.</tt> You only need this option,
|
1394
1447
|
# when you customized the name of your <tt>:counter_cache</tt> on the #belongs_to association.
|
1395
|
-
# [
|
1448
|
+
# [+:as+]
|
1396
1449
|
# Specifies a polymorphic interface (See #belongs_to).
|
1397
|
-
# [
|
1450
|
+
# [+:through+]
|
1398
1451
|
# Specifies an association through which to perform the query. This can be any other type
|
1399
1452
|
# of association, including other <tt>:through</tt> associations. Options for <tt>:class_name</tt>,
|
1400
1453
|
# <tt>:primary_key</tt> and <tt>:foreign_key</tt> are ignored, as the association uses the
|
@@ -1409,19 +1462,24 @@ module ActiveRecord
|
|
1409
1462
|
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
1410
1463
|
# join model. This allows associated records to be built which will automatically create
|
1411
1464
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1412
|
-
#
|
1413
|
-
# [
|
1465
|
+
# and 'Setting Inverses' sections above.)
|
1466
|
+
# [+:disable_joins+]
|
1467
|
+
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1468
|
+
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
1469
|
+
# due to database limitations. This option is only applicable on <tt>has_many :through</tt> associations as
|
1470
|
+
# +has_many+ alone do not perform a join.
|
1471
|
+
# [+:source+]
|
1414
1472
|
# Specifies the source association name used by #has_many <tt>:through</tt> queries.
|
1415
1473
|
# Only use it if the name cannot be inferred from the association.
|
1416
1474
|
# <tt>has_many :subscribers, through: :subscriptions</tt> will look for either <tt>:subscribers</tt> or
|
1417
1475
|
# <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
|
1418
|
-
# [
|
1476
|
+
# [+:source_type+]
|
1419
1477
|
# Specifies type of the source association used by #has_many <tt>:through</tt> queries where the source
|
1420
1478
|
# association is a polymorphic #belongs_to.
|
1421
|
-
# [
|
1479
|
+
# [+:validate+]
|
1422
1480
|
# When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
|
1423
1481
|
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1424
|
-
# [
|
1482
|
+
# [+:autosave+]
|
1425
1483
|
# If true, always save the associated objects or destroy them if marked for destruction,
|
1426
1484
|
# when saving the parent object. If false, never save or destroy the associated objects.
|
1427
1485
|
# By default, only save associated objects that are new records. This option is implemented as a
|
@@ -1430,19 +1488,24 @@ module ActiveRecord
|
|
1430
1488
|
#
|
1431
1489
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1432
1490
|
# <tt>:autosave</tt> to <tt>true</tt>.
|
1433
|
-
# [
|
1491
|
+
# [+:inverse_of+]
|
1434
1492
|
# Specifies the name of the #belongs_to association on the associated object
|
1435
1493
|
# that is the inverse of this #has_many association.
|
1436
1494
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1437
|
-
# [
|
1495
|
+
# [+:extend+]
|
1438
1496
|
# Specifies a module or array of modules that will be extended into the association object returned.
|
1439
1497
|
# Useful for defining methods on associations, especially when they should be shared between multiple
|
1440
1498
|
# association objects.
|
1441
|
-
# [
|
1442
|
-
#
|
1443
|
-
#
|
1499
|
+
# [+:strict_loading+]
|
1500
|
+
# When set to +true+, enforces strict loading every time the associated record is loaded through this
|
1501
|
+
# association.
|
1502
|
+
# [+:ensuring_owner_was+]
|
1444
1503
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
1445
1504
|
# associated records to be deleted in a background job.
|
1505
|
+
# [+:query_constraints+]
|
1506
|
+
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
1507
|
+
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
1508
|
+
# When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
|
1446
1509
|
#
|
1447
1510
|
# Option examples:
|
1448
1511
|
# has_many :comments, -> { order("posted_on") }
|
@@ -1453,7 +1516,9 @@ module ActiveRecord
|
|
1453
1516
|
# has_many :tags, as: :taggable
|
1454
1517
|
# has_many :reports, -> { readonly }
|
1455
1518
|
# has_many :subscribers, through: :subscriptions, source: :user
|
1519
|
+
# has_many :subscribers, through: :subscriptions, disable_joins: true
|
1456
1520
|
# has_many :comments, strict_loading: true
|
1521
|
+
# has_many :comments, query_constraints: [:blog_id, :post_id]
|
1457
1522
|
def has_many(name, scope = nil, **options, &extension)
|
1458
1523
|
reflection = Builder::HasMany.build(self, name, scope, options, &extension)
|
1459
1524
|
Reflection.add_reflection self, name, reflection
|
@@ -1469,37 +1534,48 @@ module ActiveRecord
|
|
1469
1534
|
# +association+ is a placeholder for the symbol passed as the +name+ argument, so
|
1470
1535
|
# <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.
|
1471
1536
|
#
|
1472
|
-
# [association]
|
1537
|
+
# [<tt>association</tt>]
|
1473
1538
|
# Returns the associated object. +nil+ is returned if none is found.
|
1474
|
-
# [association=(associate)]
|
1539
|
+
# [<tt>association=(associate)</tt>]
|
1475
1540
|
# Assigns the associate object, extracts the primary key, sets it as the foreign key,
|
1476
1541
|
# and saves the associate object. To avoid database inconsistencies, permanently deletes an existing
|
1477
1542
|
# associated object when assigning a new one, even if the new one isn't saved to database.
|
1478
|
-
# [build_association(attributes = {})]
|
1543
|
+
# [<tt>build_association(attributes = {})</tt>]
|
1479
1544
|
# Returns a new object of the associated type that has been instantiated
|
1480
1545
|
# with +attributes+ and linked to this object through a foreign key, but has not
|
1481
1546
|
# yet been saved.
|
1482
|
-
# [create_association(attributes = {})]
|
1547
|
+
# [<tt>create_association(attributes = {})</tt>]
|
1483
1548
|
# Returns a new object of the associated type that has been instantiated
|
1484
1549
|
# with +attributes+, linked to this object through a foreign key, and that
|
1485
1550
|
# has already been saved (if it passed the validation).
|
1486
|
-
# [create_association!(attributes = {})]
|
1551
|
+
# [<tt>create_association!(attributes = {})</tt>]
|
1487
1552
|
# Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
|
1488
1553
|
# if the record is invalid.
|
1489
|
-
# [reload_association]
|
1554
|
+
# [<tt>reload_association</tt>]
|
1490
1555
|
# Returns the associated object, forcing a database read.
|
1556
|
+
# [<tt>reset_association</tt>]
|
1557
|
+
# Unloads the associated object. The next access will query it from the database.
|
1558
|
+
#
|
1559
|
+
# ==== Example
|
1560
|
+
#
|
1561
|
+
# class Account < ActiveRecord::Base
|
1562
|
+
# has_one :beneficiary
|
1563
|
+
# end
|
1564
|
+
#
|
1565
|
+
# Declaring <tt>has_one :beneficiary</tt> adds the following methods (and more):
|
1491
1566
|
#
|
1492
|
-
#
|
1567
|
+
# account = Account.find(5)
|
1568
|
+
# beneficiary = Beneficiary.find(8)
|
1493
1569
|
#
|
1494
|
-
#
|
1495
|
-
#
|
1496
|
-
#
|
1497
|
-
#
|
1498
|
-
#
|
1499
|
-
#
|
1500
|
-
#
|
1570
|
+
# account.beneficiary # similar to Beneficiary.find_by(account_id: 5)
|
1571
|
+
# account.beneficiary = beneficiary # similar to beneficiary.update(account_id: 5)
|
1572
|
+
# account.build_beneficiary # similar to Beneficiary.new(account_id: 5)
|
1573
|
+
# account.create_beneficiary # similar to Beneficiary.create(account_id: 5)
|
1574
|
+
# account.create_beneficiary! # similar to Beneficiary.create!(account_id: 5)
|
1575
|
+
# account.reload_beneficiary
|
1576
|
+
# account.reset_beneficiary
|
1501
1577
|
#
|
1502
|
-
#
|
1578
|
+
# ==== Scopes
|
1503
1579
|
#
|
1504
1580
|
# You can pass a second argument +scope+ as a callable (i.e. proc or
|
1505
1581
|
# lambda) to retrieve a specific record or customize the generated query
|
@@ -1510,16 +1586,16 @@ module ActiveRecord
|
|
1510
1586
|
# has_one :employer, -> { joins(:company) }
|
1511
1587
|
# has_one :latest_post, ->(blog) { where("created_at > ?", blog.enabled_at) }
|
1512
1588
|
#
|
1513
|
-
#
|
1589
|
+
# ==== Options
|
1514
1590
|
#
|
1515
1591
|
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1516
1592
|
#
|
1517
1593
|
# Options are:
|
1518
|
-
# [
|
1594
|
+
# [+:class_name+]
|
1519
1595
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
1520
1596
|
# from the association name. So <tt>has_one :manager</tt> will by default be linked to the Manager class, but
|
1521
1597
|
# if the real class name is Person, you'll have to specify it with this option.
|
1522
|
-
# [
|
1598
|
+
# [+:dependent+]
|
1523
1599
|
# Controls what happens to the associated object when
|
1524
1600
|
# its owner is destroyed:
|
1525
1601
|
#
|
@@ -1531,66 +1607,89 @@ module ActiveRecord
|
|
1531
1607
|
# * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
|
1532
1608
|
# * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Polymorphic type column is also nullified
|
1533
1609
|
# on polymorphic associations. Callbacks are not executed.
|
1534
|
-
# * <tt>:restrict_with_exception</tt> causes an
|
1610
|
+
# * <tt>:restrict_with_exception</tt> causes an ActiveRecord::DeleteRestrictionError exception to be raised if there is an associated record
|
1535
1611
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
|
1536
1612
|
#
|
1537
1613
|
# Note that <tt>:dependent</tt> option is ignored when using <tt>:through</tt> option.
|
1538
|
-
# [
|
1614
|
+
# [+:foreign_key+]
|
1539
1615
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1540
1616
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_one association
|
1541
1617
|
# will use "person_id" as the default <tt>:foreign_key</tt>.
|
1542
1618
|
#
|
1543
|
-
#
|
1544
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
1545
|
-
# [
|
1619
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
1620
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
1621
|
+
# [+:foreign_type+]
|
1546
1622
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
1547
1623
|
# association. By default this is guessed to be the name of the polymorphic association
|
1548
1624
|
# specified on "as" option with a "_type" suffix. So a class that defines a
|
1549
1625
|
# <tt>has_one :tag, as: :taggable</tt> association will use "taggable_type" as the
|
1550
1626
|
# default <tt>:foreign_type</tt>.
|
1551
|
-
# [
|
1627
|
+
# [+:primary_key+]
|
1552
1628
|
# Specify the method that returns the primary key used for the association. By default this is +id+.
|
1553
|
-
# [
|
1629
|
+
# [+:as+]
|
1554
1630
|
# Specifies a polymorphic interface (See #belongs_to).
|
1555
|
-
# [
|
1631
|
+
# [+:through+]
|
1556
1632
|
# Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>,
|
1557
1633
|
# <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
|
1558
1634
|
# source reflection. You can only use a <tt>:through</tt> query through a #has_one
|
1559
1635
|
# or #belongs_to association on the join model.
|
1560
1636
|
#
|
1637
|
+
# If the association on the join model is a #belongs_to, the collection can be modified
|
1638
|
+
# and the records on the <tt>:through</tt> model will be automatically created and removed
|
1639
|
+
# as appropriate. Otherwise, the collection is read-only, so you should manipulate the
|
1640
|
+
# <tt>:through</tt> association directly.
|
1641
|
+
#
|
1561
1642
|
# If you are going to modify the association (rather than just read from it), then it is
|
1562
|
-
# a good idea to set the <tt>:inverse_of</tt> option
|
1563
|
-
#
|
1643
|
+
# a good idea to set the <tt>:inverse_of</tt> option on the source association on the
|
1644
|
+
# join model. This allows associated records to be built which will automatically create
|
1645
|
+
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1646
|
+
# and 'Setting Inverses' sections above.)
|
1647
|
+
# [+:disable_joins+]
|
1648
|
+
# Specifies whether joins should be skipped for an association. If set to true, two or more queries
|
1649
|
+
# will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
|
1650
|
+
# due to database limitations. This option is only applicable on <tt>has_one :through</tt> associations as
|
1651
|
+
# +has_one+ alone does not perform a join.
|
1652
|
+
# [+:source+]
|
1564
1653
|
# Specifies the source association name used by #has_one <tt>:through</tt> queries.
|
1565
1654
|
# Only use it if the name cannot be inferred from the association.
|
1566
1655
|
# <tt>has_one :favorite, through: :favorites</tt> will look for a
|
1567
1656
|
# <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
|
1568
|
-
# [
|
1657
|
+
# [+:source_type+]
|
1569
1658
|
# Specifies type of the source association used by #has_one <tt>:through</tt> queries where the source
|
1570
1659
|
# association is a polymorphic #belongs_to.
|
1571
|
-
# [
|
1660
|
+
# [+:validate+]
|
1572
1661
|
# When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
|
1573
1662
|
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1574
|
-
# [
|
1663
|
+
# [+:autosave+]
|
1575
1664
|
# If true, always save the associated object or destroy it if marked for destruction,
|
1576
1665
|
# when saving the parent object. If false, never save or destroy the associated object.
|
1577
1666
|
# By default, only save the associated object if it's a new record.
|
1578
1667
|
#
|
1579
1668
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1580
1669
|
# <tt>:autosave</tt> to <tt>true</tt>.
|
1581
|
-
# [
|
1670
|
+
# [+:touch+]
|
1671
|
+
# If true, the associated object will be touched (the +updated_at+ / +updated_on+ attributes set to current time)
|
1672
|
+
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
1673
|
+
# will be updated with the current time in addition to the +updated_at+ / +updated_on+ attribute.
|
1674
|
+
# Please note that no validation will be performed when touching, and only the +after_touch+,
|
1675
|
+
# +after_commit+, and +after_rollback+ callbacks will be executed.
|
1676
|
+
# [+:inverse_of+]
|
1582
1677
|
# Specifies the name of the #belongs_to association on the associated object
|
1583
1678
|
# that is the inverse of this #has_one association.
|
1584
1679
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1585
|
-
# [
|
1680
|
+
# [+:required+]
|
1586
1681
|
# When set to +true+, the association will also have its presence validated.
|
1587
1682
|
# This will validate the association itself, not the id. You can use
|
1588
1683
|
# +:inverse_of+ to avoid an extra query during validation.
|
1589
|
-
# [
|
1684
|
+
# [+:strict_loading+]
|
1590
1685
|
# Enforces strict loading every time the associated record is loaded through this association.
|
1591
|
-
# [
|
1686
|
+
# [+:ensuring_owner_was+]
|
1592
1687
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
1593
1688
|
# associated records to be deleted in a background job.
|
1689
|
+
# [+:query_constraints+]
|
1690
|
+
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
1691
|
+
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
1692
|
+
# When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
|
1594
1693
|
#
|
1595
1694
|
# Option examples:
|
1596
1695
|
# has_one :credit_card, dependent: :destroy # destroys the associated credit card
|
@@ -1601,9 +1700,11 @@ module ActiveRecord
|
|
1601
1700
|
# has_one :attachment, as: :attachable
|
1602
1701
|
# has_one :boss, -> { readonly }
|
1603
1702
|
# has_one :club, through: :membership
|
1703
|
+
# has_one :club, through: :membership, disable_joins: true
|
1604
1704
|
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
1605
1705
|
# has_one :credit_card, required: true
|
1606
1706
|
# has_one :credit_card, strict_loading: true
|
1707
|
+
# has_one :employment_record_book, query_constraints: [:organization_id, :employee_id]
|
1607
1708
|
def has_one(name, scope = nil, **options)
|
1608
1709
|
reflection = Builder::HasOne.build(self, name, scope, options)
|
1609
1710
|
Reflection.add_reflection self, name, reflection
|
@@ -1620,36 +1721,52 @@ module ActiveRecord
|
|
1620
1721
|
# +association+ is a placeholder for the symbol passed as the +name+ argument, so
|
1621
1722
|
# <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>.
|
1622
1723
|
#
|
1623
|
-
# [association]
|
1724
|
+
# [<tt>association</tt>]
|
1624
1725
|
# Returns the associated object. +nil+ is returned if none is found.
|
1625
|
-
# [association=(associate)]
|
1726
|
+
# [<tt>association=(associate)</tt>]
|
1626
1727
|
# Assigns the associate object, extracts the primary key, and sets it as the foreign key.
|
1627
1728
|
# No modification or deletion of existing records takes place.
|
1628
|
-
# [build_association(attributes = {})]
|
1729
|
+
# [<tt>build_association(attributes = {})</tt>]
|
1629
1730
|
# Returns a new object of the associated type that has been instantiated
|
1630
1731
|
# with +attributes+ and linked to this object through a foreign key, but has not yet been saved.
|
1631
|
-
# [create_association(attributes = {})]
|
1732
|
+
# [<tt>create_association(attributes = {})</tt>]
|
1632
1733
|
# Returns a new object of the associated type that has been instantiated
|
1633
1734
|
# with +attributes+, linked to this object through a foreign key, and that
|
1634
1735
|
# has already been saved (if it passed the validation).
|
1635
|
-
# [create_association!(attributes = {})]
|
1736
|
+
# [<tt>create_association!(attributes = {})</tt>]
|
1636
1737
|
# Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
|
1637
1738
|
# if the record is invalid.
|
1638
|
-
# [reload_association]
|
1739
|
+
# [<tt>reload_association</tt>]
|
1639
1740
|
# Returns the associated object, forcing a database read.
|
1741
|
+
# [<tt>reset_association</tt>]
|
1742
|
+
# Unloads the associated object. The next access will query it from the database.
|
1743
|
+
# [<tt>association_changed?</tt>]
|
1744
|
+
# Returns true if a new associate object has been assigned and the next save will update the foreign key.
|
1745
|
+
# [<tt>association_previously_changed?</tt>]
|
1746
|
+
# Returns true if the previous save updated the association to reference a new associate object.
|
1640
1747
|
#
|
1641
|
-
#
|
1748
|
+
# ==== Example
|
1642
1749
|
#
|
1643
|
-
#
|
1644
|
-
#
|
1645
|
-
#
|
1646
|
-
#
|
1647
|
-
#
|
1648
|
-
# * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
|
1649
|
-
# * <tt>Post#reload_author</tt>
|
1650
|
-
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1750
|
+
# class Post < ActiveRecord::Base
|
1751
|
+
# belongs_to :author
|
1752
|
+
# end
|
1753
|
+
#
|
1754
|
+
# Declaring <tt>belongs_to :author</tt> adds the following methods (and more):
|
1651
1755
|
#
|
1652
|
-
#
|
1756
|
+
# post = Post.find(7)
|
1757
|
+
# author = Author.find(19)
|
1758
|
+
#
|
1759
|
+
# post.author # similar to Author.find(post.author_id)
|
1760
|
+
# post.author = author # similar to post.author_id = author.id
|
1761
|
+
# post.build_author # similar to post.author = Author.new
|
1762
|
+
# post.create_author # similar to post.author = Author.new; post.author.save; post.author
|
1763
|
+
# post.create_author! # similar to post.author = Author.new; post.author.save!; post.author
|
1764
|
+
# post.reload_author
|
1765
|
+
# post.reset_author
|
1766
|
+
# post.author_changed?
|
1767
|
+
# post.author_previously_changed?
|
1768
|
+
#
|
1769
|
+
# ==== Scopes
|
1653
1770
|
#
|
1654
1771
|
# You can pass a second argument +scope+ as a callable (i.e. proc or
|
1655
1772
|
# lambda) to retrieve a specific record or customize the generated query
|
@@ -1660,37 +1777,39 @@ module ActiveRecord
|
|
1660
1777
|
# belongs_to :user, -> { joins(:friends) }
|
1661
1778
|
# belongs_to :level, ->(game) { where("game_level > ?", game.current_level) }
|
1662
1779
|
#
|
1663
|
-
#
|
1780
|
+
# ==== Options
|
1664
1781
|
#
|
1665
|
-
#
|
1782
|
+
# The declaration can also include an +options+ hash to specialize the behavior of the association.
|
1783
|
+
#
|
1784
|
+
# [+:class_name+]
|
1666
1785
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
1667
1786
|
# from the association name. So <tt>belongs_to :author</tt> will by default be linked to the Author class, but
|
1668
1787
|
# if the real class name is Person, you'll have to specify it with this option.
|
1669
|
-
# [
|
1788
|
+
# [+:foreign_key+]
|
1670
1789
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1671
1790
|
# of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt>
|
1672
1791
|
# association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
|
1673
1792
|
# <tt>belongs_to :favorite_person, class_name: "Person"</tt> will use a foreign key
|
1674
1793
|
# of "favorite_person_id".
|
1675
1794
|
#
|
1676
|
-
#
|
1677
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
1678
|
-
# [
|
1795
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
1796
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
1797
|
+
# [+:foreign_type+]
|
1679
1798
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
1680
1799
|
# association. By default this is guessed to be the name of the association with a "_type"
|
1681
1800
|
# suffix. So a class that defines a <tt>belongs_to :taggable, polymorphic: true</tt>
|
1682
1801
|
# association will use "taggable_type" as the default <tt>:foreign_type</tt>.
|
1683
|
-
# [
|
1802
|
+
# [+:primary_key+]
|
1684
1803
|
# Specify the method that returns the primary key of associated object used for the association.
|
1685
1804
|
# By default this is +id+.
|
1686
|
-
# [
|
1805
|
+
# [+:dependent+]
|
1687
1806
|
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
|
1688
1807
|
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. If set to
|
1689
1808
|
# <tt>:destroy_async</tt>, the associated object is scheduled to be destroyed in a background job.
|
1690
1809
|
# This option should not be specified when #belongs_to is used in conjunction with
|
1691
1810
|
# a #has_many relationship on another class because of the potential to leave
|
1692
1811
|
# orphaned records behind.
|
1693
|
-
# [
|
1812
|
+
# [+:counter_cache+]
|
1694
1813
|
# Caches the number of belonging objects on the associate class through the use of CounterCache::ClassMethods#increment_counter
|
1695
1814
|
# and CounterCache::ClassMethods#decrement_counter. The counter cache is incremented when an object of this
|
1696
1815
|
# class is created and decremented when it's destroyed. This requires that a column
|
@@ -1702,14 +1821,14 @@ module ActiveRecord
|
|
1702
1821
|
# option (e.g., <tt>counter_cache: :my_custom_counter</tt>.)
|
1703
1822
|
# Note: Specifying a counter cache will add it to that model's list of readonly attributes
|
1704
1823
|
# using +attr_readonly+.
|
1705
|
-
# [
|
1824
|
+
# [+:polymorphic+]
|
1706
1825
|
# Specify this association is a polymorphic association by passing +true+.
|
1707
1826
|
# Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
|
1708
1827
|
# to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
|
1709
|
-
# [
|
1828
|
+
# [+:validate+]
|
1710
1829
|
# When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
|
1711
1830
|
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1712
|
-
# [
|
1831
|
+
# [+:autosave+]
|
1713
1832
|
# If true, always save the associated object or destroy it if marked for destruction, when
|
1714
1833
|
# saving the parent object.
|
1715
1834
|
# If false, never save or destroy the associated object.
|
@@ -1717,32 +1836,37 @@ module ActiveRecord
|
|
1717
1836
|
#
|
1718
1837
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for
|
1719
1838
|
# sets <tt>:autosave</tt> to <tt>true</tt>.
|
1720
|
-
# [
|
1721
|
-
# If true, the associated object will be touched (the updated_at/
|
1839
|
+
# [+:touch+]
|
1840
|
+
# If true, the associated object will be touched (the +updated_at+ / +updated_on+ attributes set to current time)
|
1722
1841
|
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
1723
|
-
# will be updated with the current time in addition to the updated_at/
|
1724
|
-
# Please note that
|
1725
|
-
# +after_commit
|
1726
|
-
# [
|
1842
|
+
# will be updated with the current time in addition to the +updated_at+ / +updated_on+ attribute.
|
1843
|
+
# Please note that no validation will be performed when touching, and only the +after_touch+,
|
1844
|
+
# +after_commit+, and +after_rollback+ callbacks will be executed.
|
1845
|
+
# [+:inverse_of+]
|
1727
1846
|
# Specifies the name of the #has_one or #has_many association on the associated
|
1728
1847
|
# object that is the inverse of this #belongs_to association.
|
1729
1848
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1730
|
-
# [
|
1849
|
+
# [+:optional+]
|
1731
1850
|
# When set to +true+, the association will not have its presence validated.
|
1732
|
-
# [
|
1851
|
+
# [+:required+]
|
1733
1852
|
# When set to +true+, the association will also have its presence validated.
|
1734
1853
|
# This will validate the association itself, not the id. You can use
|
1735
1854
|
# +:inverse_of+ to avoid an extra query during validation.
|
1736
1855
|
# NOTE: <tt>required</tt> is set to <tt>true</tt> by default and is deprecated. If
|
1737
1856
|
# you don't want to have association presence validated, use <tt>optional: true</tt>.
|
1738
|
-
# [
|
1857
|
+
# [+:default+]
|
1739
1858
|
# Provide a callable (i.e. proc or lambda) to specify that the association should
|
1740
1859
|
# be initialized with a particular record before validation.
|
1741
|
-
#
|
1860
|
+
# Please note that callable won't be executed if the record exists.
|
1861
|
+
# [+:strict_loading+]
|
1742
1862
|
# Enforces strict loading every time the associated record is loaded through this association.
|
1743
|
-
# [
|
1863
|
+
# [+:ensuring_owner_was+]
|
1744
1864
|
# Specifies an instance method to be called on the owner. The method must return true in order for the
|
1745
1865
|
# associated records to be deleted in a background job.
|
1866
|
+
# [+:query_constraints+]
|
1867
|
+
# Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
|
1868
|
+
# This is an optional option. By default Rails will attempt to derive the value automatically.
|
1869
|
+
# When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
|
1746
1870
|
#
|
1747
1871
|
# Option examples:
|
1748
1872
|
# belongs_to :firm, foreign_key: "client_of"
|
@@ -1758,6 +1882,7 @@ module ActiveRecord
|
|
1758
1882
|
# belongs_to :user, optional: true
|
1759
1883
|
# belongs_to :account, default: -> { company.account }
|
1760
1884
|
# belongs_to :account, strict_loading: true
|
1885
|
+
# belong_to :note, query_constraints: [:organization_id, :note_id]
|
1761
1886
|
def belongs_to(name, scope = nil, **options)
|
1762
1887
|
reflection = Builder::BelongsTo.build(self, name, scope, options)
|
1763
1888
|
Reflection.add_reflection self, name, reflection
|
@@ -1780,7 +1905,7 @@ module ActiveRecord
|
|
1780
1905
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1781
1906
|
# join table with a migration such as this:
|
1782
1907
|
#
|
1783
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[
|
1908
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.1]
|
1784
1909
|
# def change
|
1785
1910
|
# create_join_table :developers, :projects
|
1786
1911
|
# end
|
@@ -1795,71 +1920,80 @@ module ActiveRecord
|
|
1795
1920
|
# +collection+ is a placeholder for the symbol passed as the +name+ argument, so
|
1796
1921
|
# <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.
|
1797
1922
|
#
|
1798
|
-
# [collection]
|
1923
|
+
# [<tt>collection</tt>]
|
1799
1924
|
# Returns a Relation of all the associated objects.
|
1800
1925
|
# An empty Relation is returned if none are found.
|
1801
|
-
# [collection<<(object, ...)]
|
1926
|
+
# [<tt>collection<<(object, ...)</tt>]
|
1802
1927
|
# Adds one or more objects to the collection by creating associations in the join table
|
1803
1928
|
# (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
|
1804
1929
|
# Note that this operation instantly fires update SQL without waiting for the save or update call on the
|
1805
1930
|
# parent object, unless the parent object is a new record.
|
1806
|
-
# [collection.delete(object, ...)]
|
1931
|
+
# [<tt>collection.delete(object, ...)</tt>]
|
1807
1932
|
# Removes one or more objects from the collection by removing their associations from the join table.
|
1808
1933
|
# This does not destroy the objects.
|
1809
|
-
# [collection.destroy(object, ...)]
|
1934
|
+
# [<tt>collection.destroy(object, ...)</tt>]
|
1810
1935
|
# Removes one or more objects from the collection by running destroy on each association in the join table, overriding any dependent option.
|
1811
1936
|
# This does not destroy the objects.
|
1812
|
-
# [collection=objects]
|
1937
|
+
# [<tt>collection=objects</tt>]
|
1813
1938
|
# Replaces the collection's content by deleting and adding objects as appropriate.
|
1814
|
-
# [collection_singular_ids]
|
1939
|
+
# [<tt>collection_singular_ids</tt>]
|
1815
1940
|
# Returns an array of the associated objects' ids.
|
1816
|
-
# [collection_singular_ids=ids]
|
1941
|
+
# [<tt>collection_singular_ids=ids</tt>]
|
1817
1942
|
# Replace the collection by the objects identified by the primary keys in +ids+.
|
1818
|
-
# [collection.clear]
|
1943
|
+
# [<tt>collection.clear</tt>]
|
1819
1944
|
# Removes every object from the collection. This does not destroy the objects.
|
1820
|
-
# [collection.empty
|
1945
|
+
# [<tt>collection.empty?</tt>]
|
1821
1946
|
# Returns +true+ if there are no associated objects.
|
1822
|
-
# [collection.size]
|
1947
|
+
# [<tt>collection.size</tt>]
|
1823
1948
|
# Returns the number of associated objects.
|
1824
|
-
# [collection.find(id)]
|
1949
|
+
# [<tt>collection.find(id)</tt>]
|
1825
1950
|
# Finds an associated object responding to the +id+ and that
|
1826
1951
|
# meets the condition that it has to be associated with this object.
|
1827
1952
|
# Uses the same rules as ActiveRecord::FinderMethods#find.
|
1828
|
-
# [collection.exists?(...)]
|
1953
|
+
# [<tt>collection.exists?(...)</tt>]
|
1829
1954
|
# Checks whether an associated object with the given conditions exists.
|
1830
1955
|
# Uses the same rules as ActiveRecord::FinderMethods#exists?.
|
1831
|
-
# [collection.build(attributes = {})]
|
1956
|
+
# [<tt>collection.build(attributes = {})</tt>]
|
1832
1957
|
# Returns a new object of the collection type that has been instantiated
|
1833
1958
|
# with +attributes+ and linked to this object through the join table, but has not yet been saved.
|
1834
|
-
# [collection.create(attributes = {})]
|
1959
|
+
# [<tt>collection.create(attributes = {})</tt>]
|
1835
1960
|
# Returns a new object of the collection type that has been instantiated
|
1836
1961
|
# with +attributes+, linked to this object through the join table, and that has already been
|
1837
1962
|
# saved (if it passed the validation).
|
1838
|
-
# [collection.reload]
|
1963
|
+
# [<tt>collection.reload</tt>]
|
1839
1964
|
# Returns a Relation of all of the associated objects, forcing a database read.
|
1840
1965
|
# An empty Relation is returned if none are found.
|
1841
1966
|
#
|
1842
|
-
#
|
1843
|
-
#
|
1844
|
-
#
|
1845
|
-
#
|
1846
|
-
#
|
1847
|
-
#
|
1848
|
-
#
|
1849
|
-
#
|
1850
|
-
#
|
1851
|
-
#
|
1852
|
-
#
|
1853
|
-
#
|
1854
|
-
#
|
1855
|
-
#
|
1856
|
-
#
|
1857
|
-
#
|
1858
|
-
#
|
1859
|
-
#
|
1967
|
+
# ==== Example
|
1968
|
+
#
|
1969
|
+
# class Developer < ActiveRecord::Base
|
1970
|
+
# has_and_belongs_to_many :projects
|
1971
|
+
# end
|
1972
|
+
#
|
1973
|
+
# Declaring <tt>has_and_belongs_to_many :projects</tt> adds the following methods (and more):
|
1974
|
+
#
|
1975
|
+
# developer = Developer.find(11)
|
1976
|
+
# project = Project.find(9)
|
1977
|
+
#
|
1978
|
+
# developer.projects
|
1979
|
+
# developer.projects << project
|
1980
|
+
# developer.projects.delete(project)
|
1981
|
+
# developer.projects.destroy(project)
|
1982
|
+
# developer.projects = [project]
|
1983
|
+
# developer.project_ids
|
1984
|
+
# developer.project_ids = [9]
|
1985
|
+
# developer.projects.clear
|
1986
|
+
# developer.projects.empty?
|
1987
|
+
# developer.projects.size
|
1988
|
+
# developer.projects.find(9)
|
1989
|
+
# developer.projects.exists?(9)
|
1990
|
+
# developer.projects.build # similar to Project.new(developer_id: 11)
|
1991
|
+
# developer.projects.create # similar to Project.create(developer_id: 11)
|
1992
|
+
# developer.projects.reload
|
1993
|
+
#
|
1860
1994
|
# The declaration may include an +options+ hash to specialize the behavior of the association.
|
1861
1995
|
#
|
1862
|
-
#
|
1996
|
+
# ==== Scopes
|
1863
1997
|
#
|
1864
1998
|
# You can pass a second argument +scope+ as a callable (i.e. proc or
|
1865
1999
|
# lambda) to retrieve a specific set of records or customize the generated
|
@@ -1871,11 +2005,11 @@ module ActiveRecord
|
|
1871
2005
|
# where("default_category = ?", post.default_category)
|
1872
2006
|
# }
|
1873
2007
|
#
|
1874
|
-
#
|
2008
|
+
# ==== Extensions
|
1875
2009
|
#
|
1876
2010
|
# The +extension+ argument allows you to pass a block into a
|
1877
2011
|
# has_and_belongs_to_many association. This is useful for adding new
|
1878
|
-
# finders, creators and other factory-type methods to be used as part of
|
2012
|
+
# finders, creators, and other factory-type methods to be used as part of
|
1879
2013
|
# the association.
|
1880
2014
|
#
|
1881
2015
|
# Extension examples:
|
@@ -1886,33 +2020,33 @@ module ActiveRecord
|
|
1886
2020
|
# end
|
1887
2021
|
# end
|
1888
2022
|
#
|
1889
|
-
#
|
2023
|
+
# ==== Options
|
1890
2024
|
#
|
1891
|
-
# [
|
2025
|
+
# [+:class_name+]
|
1892
2026
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
1893
2027
|
# from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the
|
1894
2028
|
# Project class, but if the real class name is SuperProject, you'll have to specify it with this option.
|
1895
|
-
# [
|
2029
|
+
# [+:join_table+]
|
1896
2030
|
# Specify the name of the join table if the default based on lexical order isn't what you want.
|
1897
2031
|
# <b>WARNING:</b> If you're overwriting the table name of either class, the +table_name+ method
|
1898
2032
|
# MUST be declared underneath any #has_and_belongs_to_many declaration in order to work.
|
1899
|
-
# [
|
2033
|
+
# [+:foreign_key+]
|
1900
2034
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1901
2035
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes
|
1902
2036
|
# a #has_and_belongs_to_many association to Project will use "person_id" as the
|
1903
2037
|
# default <tt>:foreign_key</tt>.
|
1904
2038
|
#
|
1905
|
-
#
|
1906
|
-
# a good idea to set the <tt>:inverse_of</tt> option.
|
1907
|
-
# [
|
2039
|
+
# Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
|
2040
|
+
# inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
|
2041
|
+
# [+:association_foreign_key+]
|
1908
2042
|
# Specify the foreign key used for the association on the receiving side of the association.
|
1909
2043
|
# By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
|
1910
2044
|
# So if a Person class makes a #has_and_belongs_to_many association to Project,
|
1911
2045
|
# the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
|
1912
|
-
# [
|
2046
|
+
# [+:validate+]
|
1913
2047
|
# When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
|
1914
2048
|
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1915
|
-
# [
|
2049
|
+
# [+:autosave+]
|
1916
2050
|
# If true, always save the associated objects or destroy them if marked for destruction, when
|
1917
2051
|
# saving the parent object.
|
1918
2052
|
# If false, never save or destroy the associated objects.
|
@@ -1920,7 +2054,7 @@ module ActiveRecord
|
|
1920
2054
|
#
|
1921
2055
|
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1922
2056
|
# <tt>:autosave</tt> to <tt>true</tt>.
|
1923
|
-
# [
|
2057
|
+
# [+:strict_loading+]
|
1924
2058
|
# Enforces strict loading every time an associated record is loaded through this association.
|
1925
2059
|
#
|
1926
2060
|
# Option examples:
|