activerecord 4.2.6 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1307 -1105
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -8
- data/examples/performance.rb +2 -3
- data/examples/simple.rb +0 -1
- data/lib/active_record/aggregations.rb +37 -23
- data/lib/active_record/association_relation.rb +3 -3
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +11 -9
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +21 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +43 -18
- data/lib/active_record/associations/builder/collection_association.rb +7 -19
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +11 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -10
- data/lib/active_record/associations/collection_association.rb +50 -31
- data/lib/active_record/associations/collection_proxy.rb +69 -29
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -47
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
- data/lib/active_record/associations/join_dependency.rb +29 -19
- data/lib/active_record/associations/preloader/association.rb +46 -52
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +27 -14
- data/lib/active_record/associations/preloader.rb +14 -4
- data/lib/active_record/associations/singular_association.rb +7 -1
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/associations.rb +317 -209
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute.rb +68 -18
- data/lib/active_record/attribute_assignment.rb +20 -141
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +31 -59
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
- data/lib/active_record/attribute_methods/write.rb +14 -38
- data/lib/active_record/attribute_methods.rb +70 -45
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attributes.rb +199 -80
- data/lib/active_record/autosave_association.rb +49 -16
- data/lib/active_record/base.rb +32 -23
- data/lib/active_record/callbacks.rb +39 -43
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +40 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +378 -140
- data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
- data/lib/active_record/connection_adapters/abstract_adapter.rb +153 -59
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -362
- data/lib/active_record/connection_adapters/column.rb +28 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +25 -176
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +148 -203
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +37 -14
- data/lib/active_record/core.rb +89 -107
- data/lib/active_record/counter_cache.rb +13 -24
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +113 -76
- data/lib/active_record/errors.rb +87 -48
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/internal_metadata.rb +56 -0
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +15 -15
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +43 -21
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/migration.rb +364 -109
- data/lib/active_record/model_schema.rb +128 -38
- data/lib/active_record/nested_attributes.rb +58 -29
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +121 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- data/lib/active_record/railtie.rb +27 -18
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +58 -45
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +282 -115
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/calculations.rb +80 -102
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +163 -81
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +16 -42
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -15
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +120 -107
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +308 -244
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -7
- data/lib/active_record/relation/where_clause.rb +174 -0
- data/lib/active_record/relation/where_clause_factory.rb +38 -0
- data/lib/active_record/relation.rb +176 -116
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +95 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +62 -38
- data/lib/active_record/schema_migration.rb +11 -17
- data/lib/active_record/scoping/default.rb +23 -9
- data/lib/active_record/scoping/named.rb +49 -28
- data/lib/active_record/scoping.rb +32 -15
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +16 -14
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +68 -0
- data/lib/active_record/tasks/database_tasks.rb +58 -41
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -20
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +20 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -41
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +29 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +15 -14
- data/lib/active_record/type/time.rb +10 -16
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/validations/absence.rb +23 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +11 -12
- data/lib/active_record/validations/uniqueness.rb +30 -29
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record.rb +7 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +58 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -50
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -105
@@ -5,95 +5,170 @@ require 'active_record/errors'
|
|
5
5
|
|
6
6
|
module ActiveRecord
|
7
7
|
class AssociationNotFoundError < ConfigurationError #:nodoc:
|
8
|
-
def initialize(record, association_name)
|
9
|
-
|
8
|
+
def initialize(record = nil, association_name = nil)
|
9
|
+
if record && association_name
|
10
|
+
super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?")
|
11
|
+
else
|
12
|
+
super("Association was not found.")
|
13
|
+
end
|
10
14
|
end
|
11
15
|
end
|
12
16
|
|
13
17
|
class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
|
14
|
-
def initialize(reflection, associated_class = nil)
|
15
|
-
|
18
|
+
def initialize(reflection = nil, associated_class = nil)
|
19
|
+
if reflection
|
20
|
+
super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
|
21
|
+
else
|
22
|
+
super("Could not find the inverse association.")
|
23
|
+
end
|
16
24
|
end
|
17
25
|
end
|
18
26
|
|
19
27
|
class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc:
|
20
|
-
def initialize(owner_class_name, reflection)
|
21
|
-
|
28
|
+
def initialize(owner_class_name = nil, reflection = nil)
|
29
|
+
if owner_class_name && reflection
|
30
|
+
super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class_name}")
|
31
|
+
else
|
32
|
+
super("Could not find the association.")
|
33
|
+
end
|
22
34
|
end
|
23
35
|
end
|
24
36
|
|
25
37
|
class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError #:nodoc:
|
26
|
-
def initialize(owner_class_name, reflection, source_reflection)
|
27
|
-
|
38
|
+
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
39
|
+
if owner_class_name && reflection && source_reflection
|
40
|
+
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.")
|
41
|
+
else
|
42
|
+
super("Cannot have a has_many :through association.")
|
43
|
+
end
|
28
44
|
end
|
29
45
|
end
|
30
46
|
|
31
47
|
class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError #:nodoc:
|
32
|
-
def initialize(owner_class_name, reflection)
|
33
|
-
|
48
|
+
def initialize(owner_class_name = nil, reflection = nil)
|
49
|
+
if owner_class_name && reflection
|
50
|
+
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}'.")
|
51
|
+
else
|
52
|
+
super("Cannot have a has_many :through association.")
|
53
|
+
end
|
34
54
|
end
|
35
55
|
end
|
36
56
|
|
37
57
|
class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError #:nodoc:
|
38
|
-
def initialize(owner_class_name, reflection, source_reflection)
|
39
|
-
|
58
|
+
def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
|
59
|
+
if owner_class_name && reflection && source_reflection
|
60
|
+
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.")
|
61
|
+
else
|
62
|
+
super("Cannot have a has_many :through association.")
|
63
|
+
end
|
40
64
|
end
|
41
65
|
end
|
42
66
|
|
43
67
|
class HasOneThroughCantAssociateThroughCollection < ActiveRecordError #:nodoc:
|
44
|
-
def initialize(owner_class_name, reflection, through_reflection)
|
45
|
-
|
68
|
+
def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
|
69
|
+
if owner_class_name && reflection && through_reflection
|
70
|
+
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.")
|
71
|
+
else
|
72
|
+
super("Cannot have a has_one :through association.")
|
73
|
+
end
|
46
74
|
end
|
47
75
|
end
|
48
76
|
|
49
77
|
class HasOneAssociationPolymorphicThroughError < ActiveRecordError #:nodoc:
|
50
|
-
def initialize(owner_class_name, reflection)
|
51
|
-
|
78
|
+
def initialize(owner_class_name = nil, reflection = nil)
|
79
|
+
if owner_class_name && reflection
|
80
|
+
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}'.")
|
81
|
+
else
|
82
|
+
super("Cannot have a has_one :through association.")
|
83
|
+
end
|
52
84
|
end
|
53
85
|
end
|
54
86
|
|
55
87
|
class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc:
|
56
|
-
def initialize(reflection)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
88
|
+
def initialize(reflection = nil)
|
89
|
+
if reflection
|
90
|
+
through_reflection = reflection.through_reflection
|
91
|
+
source_reflection_names = reflection.source_reflection_names
|
92
|
+
source_associations = reflection.through_reflection.klass._reflections.keys
|
93
|
+
super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ', :locale => :en)} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ', :locale => :en)}?")
|
94
|
+
else
|
95
|
+
super("Could not find the source association(s).")
|
96
|
+
end
|
61
97
|
end
|
62
98
|
end
|
63
99
|
|
64
|
-
class
|
65
|
-
def initialize(owner, reflection)
|
66
|
-
|
100
|
+
class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError #:nodoc:
|
101
|
+
def initialize(owner = nil, reflection = nil)
|
102
|
+
if owner && reflection
|
103
|
+
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}.")
|
104
|
+
else
|
105
|
+
super("Cannot modify association.")
|
106
|
+
end
|
67
107
|
end
|
68
108
|
end
|
69
109
|
|
110
|
+
class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
|
111
|
+
end
|
112
|
+
|
113
|
+
class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
|
114
|
+
end
|
115
|
+
|
70
116
|
class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc:
|
71
|
-
def initialize(owner, reflection)
|
72
|
-
|
117
|
+
def initialize(owner = nil, reflection = nil)
|
118
|
+
if owner && reflection
|
119
|
+
super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.")
|
120
|
+
else
|
121
|
+
super("Cannot associate new records.")
|
122
|
+
end
|
73
123
|
end
|
74
124
|
end
|
75
125
|
|
76
126
|
class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc:
|
77
|
-
def initialize(owner, reflection)
|
78
|
-
|
127
|
+
def initialize(owner = nil, reflection = nil)
|
128
|
+
if owner && reflection
|
129
|
+
super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.")
|
130
|
+
else
|
131
|
+
super("Cannot dissociate new records.")
|
132
|
+
end
|
79
133
|
end
|
80
134
|
end
|
81
135
|
|
82
|
-
class
|
83
|
-
def initialize(owner, reflection)
|
84
|
-
|
136
|
+
class ThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc:
|
137
|
+
def initialize(owner = nil, reflection = nil)
|
138
|
+
if owner && reflection
|
139
|
+
super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
|
140
|
+
else
|
141
|
+
super("Through nested associations are read-only.")
|
142
|
+
end
|
85
143
|
end
|
86
144
|
end
|
87
145
|
|
88
|
-
class
|
89
|
-
|
90
|
-
|
146
|
+
class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly #:nodoc:
|
147
|
+
end
|
148
|
+
|
149
|
+
class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly #:nodoc:
|
150
|
+
end
|
151
|
+
|
152
|
+
# This error is raised when trying to eager load a polymorphic association using a JOIN.
|
153
|
+
# Eager loading polymorphic associations is only possible with
|
154
|
+
# {ActiveRecord::Relation#preload}[rdoc-ref:QueryMethods#preload].
|
155
|
+
class EagerLoadPolymorphicError < ActiveRecordError
|
156
|
+
def initialize(reflection = nil)
|
157
|
+
if reflection
|
158
|
+
super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}")
|
159
|
+
else
|
160
|
+
super("Eager load polymorphic error.")
|
161
|
+
end
|
91
162
|
end
|
92
163
|
end
|
93
164
|
|
94
165
|
class ReadOnlyAssociation < ActiveRecordError #:nodoc:
|
95
|
-
def initialize(reflection)
|
96
|
-
|
166
|
+
def initialize(reflection = nil)
|
167
|
+
if reflection
|
168
|
+
super("Cannot add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.")
|
169
|
+
else
|
170
|
+
super("Read-only reflection error.")
|
171
|
+
end
|
97
172
|
end
|
98
173
|
end
|
99
174
|
|
@@ -101,8 +176,12 @@ module ActiveRecord
|
|
101
176
|
# (has_many, has_one) when there is at least 1 child associated instance.
|
102
177
|
# ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
|
103
178
|
class DeleteRestrictionError < ActiveRecordError #:nodoc:
|
104
|
-
def initialize(name)
|
105
|
-
|
179
|
+
def initialize(name = nil)
|
180
|
+
if name
|
181
|
+
super("Cannot delete record because of dependent #{name}")
|
182
|
+
else
|
183
|
+
super("Delete restriction error.")
|
184
|
+
end
|
106
185
|
end
|
107
186
|
end
|
108
187
|
|
@@ -113,19 +192,19 @@ module ActiveRecord
|
|
113
192
|
|
114
193
|
# These classes will be loaded when associations are created.
|
115
194
|
# So there is no need to eager load them.
|
116
|
-
autoload :Association
|
117
|
-
autoload :SingularAssociation
|
118
|
-
autoload :CollectionAssociation
|
119
|
-
autoload :ForeignAssociation
|
120
|
-
autoload :CollectionProxy
|
195
|
+
autoload :Association
|
196
|
+
autoload :SingularAssociation
|
197
|
+
autoload :CollectionAssociation
|
198
|
+
autoload :ForeignAssociation
|
199
|
+
autoload :CollectionProxy
|
121
200
|
|
122
|
-
autoload :BelongsToAssociation
|
123
|
-
autoload :BelongsToPolymorphicAssociation
|
124
|
-
autoload :HasManyAssociation
|
125
|
-
autoload :HasManyThroughAssociation
|
126
|
-
autoload :HasOneAssociation
|
127
|
-
autoload :HasOneThroughAssociation
|
128
|
-
autoload :ThroughAssociation
|
201
|
+
autoload :BelongsToAssociation
|
202
|
+
autoload :BelongsToPolymorphicAssociation
|
203
|
+
autoload :HasManyAssociation
|
204
|
+
autoload :HasManyThroughAssociation
|
205
|
+
autoload :HasOneAssociation
|
206
|
+
autoload :HasOneThroughAssociation
|
207
|
+
autoload :ThroughAssociation
|
129
208
|
|
130
209
|
module Builder #:nodoc:
|
131
210
|
autoload :Association, 'active_record/associations/builder/association'
|
@@ -139,26 +218,20 @@ module ActiveRecord
|
|
139
218
|
end
|
140
219
|
|
141
220
|
eager_autoload do
|
142
|
-
autoload :Preloader
|
143
|
-
autoload :JoinDependency
|
144
|
-
autoload :AssociationScope
|
145
|
-
autoload :AliasTracker
|
146
|
-
end
|
147
|
-
|
148
|
-
# Clears out the association cache.
|
149
|
-
def clear_association_cache #:nodoc:
|
150
|
-
@association_cache.clear if persisted?
|
221
|
+
autoload :Preloader
|
222
|
+
autoload :JoinDependency
|
223
|
+
autoload :AssociationScope
|
224
|
+
autoload :AliasTracker
|
151
225
|
end
|
152
226
|
|
153
|
-
# :nodoc:
|
154
|
-
attr_reader :association_cache
|
155
|
-
|
156
227
|
# Returns the association instance for the given name, instantiating it if it doesn't already exist
|
157
228
|
def association(name) #:nodoc:
|
158
229
|
association = association_instance_get(name)
|
159
230
|
|
160
231
|
if association.nil?
|
161
|
-
|
232
|
+
unless reflection = self.class._reflect_on_association(name)
|
233
|
+
raise AssociationNotFoundError.new(self, name)
|
234
|
+
end
|
162
235
|
association = reflection.association_class.new(self, reflection)
|
163
236
|
association_instance_set(name, association)
|
164
237
|
end
|
@@ -166,8 +239,32 @@ module ActiveRecord
|
|
166
239
|
association
|
167
240
|
end
|
168
241
|
|
242
|
+
def association_cached?(name) # :nodoc
|
243
|
+
@association_cache.key?(name)
|
244
|
+
end
|
245
|
+
|
246
|
+
def initialize_dup(*) # :nodoc:
|
247
|
+
@association_cache = {}
|
248
|
+
super
|
249
|
+
end
|
250
|
+
|
251
|
+
def reload(*) # :nodoc:
|
252
|
+
clear_association_cache
|
253
|
+
super
|
254
|
+
end
|
255
|
+
|
169
256
|
private
|
170
|
-
#
|
257
|
+
# Clears out the association cache.
|
258
|
+
def clear_association_cache # :nodoc:
|
259
|
+
@association_cache.clear if persisted?
|
260
|
+
end
|
261
|
+
|
262
|
+
def init_internals # :nodoc:
|
263
|
+
@association_cache = {}
|
264
|
+
super
|
265
|
+
end
|
266
|
+
|
267
|
+
# Returns the specified association instance if it exists, nil otherwise.
|
171
268
|
def association_instance_get(name)
|
172
269
|
@association_cache[name]
|
173
270
|
end
|
@@ -204,7 +301,7 @@ module ActiveRecord
|
|
204
301
|
# === A word of warning
|
205
302
|
#
|
206
303
|
# Don't create associations that have the same name as instance methods of
|
207
|
-
#
|
304
|
+
# ActiveRecord::Base. Since the association adds a method with that name to
|
208
305
|
# its model, it will override the inherited method and break things.
|
209
306
|
# For instance, +attributes+ and +connection+ would be bad choices for association names.
|
210
307
|
#
|
@@ -221,7 +318,7 @@ module ActiveRecord
|
|
221
318
|
# create_other(attributes={}) | X | | X
|
222
319
|
# create_other!(attributes={}) | X | | X
|
223
320
|
#
|
224
|
-
# ===Collection associations (one-to-many / many-to-many)
|
321
|
+
# === Collection associations (one-to-many / many-to-many)
|
225
322
|
# | | | has_many
|
226
323
|
# generated methods | habtm | has_many | :through
|
227
324
|
# ----------------------------------+-------+----------+----------
|
@@ -248,7 +345,6 @@ module ActiveRecord
|
|
248
345
|
# others.find(*args) | X | X | X
|
249
346
|
# others.exists? | X | X | X
|
250
347
|
# others.distinct | X | X | X
|
251
|
-
# others.uniq | X | X | X
|
252
348
|
# others.reset | X | X | X
|
253
349
|
#
|
254
350
|
# === Overriding generated methods
|
@@ -267,7 +363,7 @@ module ActiveRecord
|
|
267
363
|
# end
|
268
364
|
#
|
269
365
|
# If your model class is <tt>Project</tt>, the module is
|
270
|
-
# named <tt>Project::
|
366
|
+
# named <tt>Project::GeneratedAssociationMethods</tt>. The +GeneratedAssociationMethods+ module is
|
271
367
|
# included in the model class immediately after the (anonymous) generated attributes methods
|
272
368
|
# module, meaning an association will override the methods for an attribute with the same name.
|
273
369
|
#
|
@@ -275,12 +371,12 @@ module ActiveRecord
|
|
275
371
|
#
|
276
372
|
# Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
|
277
373
|
# relationships between models. Each model uses an association to describe its role in
|
278
|
-
# the relation. The
|
374
|
+
# the relation. The #belongs_to association is always used in the model that has
|
279
375
|
# the foreign key.
|
280
376
|
#
|
281
377
|
# === One-to-one
|
282
378
|
#
|
283
|
-
# Use
|
379
|
+
# Use #has_one in the base, and #belongs_to in the associated model.
|
284
380
|
#
|
285
381
|
# class Employee < ActiveRecord::Base
|
286
382
|
# has_one :office
|
@@ -291,7 +387,7 @@ module ActiveRecord
|
|
291
387
|
#
|
292
388
|
# === One-to-many
|
293
389
|
#
|
294
|
-
# Use
|
390
|
+
# Use #has_many in the base, and #belongs_to in the associated model.
|
295
391
|
#
|
296
392
|
# class Manager < ActiveRecord::Base
|
297
393
|
# has_many :employees
|
@@ -304,7 +400,7 @@ module ActiveRecord
|
|
304
400
|
#
|
305
401
|
# There are two ways to build a many-to-many relationship.
|
306
402
|
#
|
307
|
-
# The first way uses a
|
403
|
+
# The first way uses a #has_many association with the <tt>:through</tt> option and a join model, so
|
308
404
|
# there are two stages of associations.
|
309
405
|
#
|
310
406
|
# class Assignment < ActiveRecord::Base
|
@@ -320,7 +416,7 @@ module ActiveRecord
|
|
320
416
|
# has_many :programmers, through: :assignments
|
321
417
|
# end
|
322
418
|
#
|
323
|
-
# For the second way, use
|
419
|
+
# For the second way, use #has_and_belongs_to_many in both models. This requires a join table
|
324
420
|
# that has no corresponding model or primary key.
|
325
421
|
#
|
326
422
|
# class Programmer < ActiveRecord::Base
|
@@ -332,13 +428,13 @@ module ActiveRecord
|
|
332
428
|
#
|
333
429
|
# Choosing which way to build a many-to-many relationship is not always simple.
|
334
430
|
# If you need to work with the relationship model as its own entity,
|
335
|
-
# use <tt
|
431
|
+
# use #has_many <tt>:through</tt>. Use #has_and_belongs_to_many when working with legacy schemas or when
|
336
432
|
# you never work directly with the relationship itself.
|
337
433
|
#
|
338
|
-
# == Is it a
|
434
|
+
# == Is it a #belongs_to or #has_one association?
|
339
435
|
#
|
340
436
|
# Both express a 1-1 relationship. The difference is mostly where to place the foreign
|
341
|
-
# key, which goes on the table for the class declaring the
|
437
|
+
# key, which goes on the table for the class declaring the #belongs_to relationship.
|
342
438
|
#
|
343
439
|
# class User < ActiveRecord::Base
|
344
440
|
# # I reference an account.
|
@@ -353,14 +449,14 @@ module ActiveRecord
|
|
353
449
|
# The tables for these classes could look something like:
|
354
450
|
#
|
355
451
|
# CREATE TABLE users (
|
356
|
-
# id int
|
357
|
-
# account_id int
|
452
|
+
# id int NOT NULL auto_increment,
|
453
|
+
# account_id int default NULL,
|
358
454
|
# name varchar default NULL,
|
359
455
|
# PRIMARY KEY (id)
|
360
456
|
# )
|
361
457
|
#
|
362
458
|
# CREATE TABLE accounts (
|
363
|
-
# id int
|
459
|
+
# id int NOT NULL auto_increment,
|
364
460
|
# name varchar default NULL,
|
365
461
|
# PRIMARY KEY (id)
|
366
462
|
# )
|
@@ -371,35 +467,35 @@ module ActiveRecord
|
|
371
467
|
# there is some special behavior you should be aware of, mostly involving the saving of
|
372
468
|
# associated objects.
|
373
469
|
#
|
374
|
-
# You can set the <tt>:autosave</tt> option on a
|
375
|
-
#
|
470
|
+
# You can set the <tt>:autosave</tt> option on a #has_one, #belongs_to,
|
471
|
+
# #has_many, or #has_and_belongs_to_many association. Setting it
|
376
472
|
# to +true+ will _always_ save the members, whereas setting it to +false+ will
|
377
473
|
# _never_ save the members. More details about <tt>:autosave</tt> option is available at
|
378
474
|
# AutosaveAssociation.
|
379
475
|
#
|
380
476
|
# === One-to-one associations
|
381
477
|
#
|
382
|
-
# * Assigning an object to a
|
478
|
+
# * Assigning an object to a #has_one association automatically saves that object and
|
383
479
|
# the object being replaced (if there is one), in order to update their foreign
|
384
480
|
# keys - except if the parent object is unsaved (<tt>new_record? == true</tt>).
|
385
481
|
# * If either of these saves fail (due to one of the objects being invalid), an
|
386
|
-
#
|
482
|
+
# ActiveRecord::RecordNotSaved exception is raised and the assignment is
|
387
483
|
# cancelled.
|
388
|
-
# * If you wish to assign an object to a
|
389
|
-
# use the <tt
|
484
|
+
# * If you wish to assign an object to a #has_one association without saving it,
|
485
|
+
# use the <tt>#build_association</tt> method (documented below). The object being
|
390
486
|
# replaced will still be saved to update its foreign key.
|
391
|
-
# * Assigning an object to a
|
487
|
+
# * Assigning an object to a #belongs_to association does not save the object, since
|
392
488
|
# the foreign key field belongs on the parent. It does not save the parent either.
|
393
489
|
#
|
394
490
|
# === Collections
|
395
491
|
#
|
396
|
-
# * Adding an object to a collection (
|
492
|
+
# * Adding an object to a collection (#has_many or #has_and_belongs_to_many) automatically
|
397
493
|
# saves that object, except if the parent object (the owner of the collection) is not yet
|
398
494
|
# stored in the database.
|
399
495
|
# * If saving any of the objects being added to a collection (via <tt>push</tt> or similar)
|
400
496
|
# fails, then <tt>push</tt> returns +false+.
|
401
497
|
# * If saving fails while replacing the collection (via <tt>association=</tt>), an
|
402
|
-
#
|
498
|
+
# ActiveRecord::RecordNotSaved exception is raised and the assignment is
|
403
499
|
# cancelled.
|
404
500
|
# * You can add an object to a collection without automatically saving it by using the
|
405
501
|
# <tt>collection.build</tt> method (documented below).
|
@@ -408,14 +504,14 @@ module ActiveRecord
|
|
408
504
|
#
|
409
505
|
# == Customizing the query
|
410
506
|
#
|
411
|
-
# \Associations are built from <tt>Relation</tt>
|
507
|
+
# \Associations are built from <tt>Relation</tt> objects, and you can use the Relation syntax
|
412
508
|
# to customize them. For example, to add a condition:
|
413
509
|
#
|
414
510
|
# class Blog < ActiveRecord::Base
|
415
|
-
# has_many :published_posts, -> { where
|
511
|
+
# has_many :published_posts, -> { where(published: true) }, class_name: 'Post'
|
416
512
|
# end
|
417
513
|
#
|
418
|
-
# Inside the <tt>-> { ... }</tt> block you can use all of the usual
|
514
|
+
# Inside the <tt>-> { ... }</tt> block you can use all of the usual Relation methods.
|
419
515
|
#
|
420
516
|
# === Accessing the owner object
|
421
517
|
#
|
@@ -424,7 +520,7 @@ module ActiveRecord
|
|
424
520
|
# events that occur on the user's birthday:
|
425
521
|
#
|
426
522
|
# class User < ActiveRecord::Base
|
427
|
-
# has_many :birthday_events, ->(user) { where
|
523
|
+
# has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
|
428
524
|
# end
|
429
525
|
#
|
430
526
|
# Note: Joining, eager loading and preloading of these associations is not fully possible.
|
@@ -503,8 +599,8 @@ module ActiveRecord
|
|
503
599
|
#
|
504
600
|
# * <tt>record.association(:items).owner</tt> - Returns the object the association is part of.
|
505
601
|
# * <tt>record.association(:items).reflection</tt> - Returns the reflection object that describes the association.
|
506
|
-
# * <tt>record.association(:items).target</tt> - Returns the associated object for
|
507
|
-
# the collection of associated objects for
|
602
|
+
# * <tt>record.association(:items).target</tt> - Returns the associated object for #belongs_to and #has_one, or
|
603
|
+
# the collection of associated objects for #has_many and #has_and_belongs_to_many.
|
508
604
|
#
|
509
605
|
# However, inside the actual extension code, you will not have access to the <tt>record</tt> as
|
510
606
|
# above. In this case, you can access <tt>proxy_association</tt>. For example,
|
@@ -516,7 +612,7 @@ module ActiveRecord
|
|
516
612
|
#
|
517
613
|
# Has Many associations can be configured with the <tt>:through</tt> option to use an
|
518
614
|
# explicit join model to retrieve the data. This operates similarly to a
|
519
|
-
#
|
615
|
+
# #has_and_belongs_to_many association. The advantage is that you're able to add validations,
|
520
616
|
# callbacks, and extra attributes on the join model. Consider the following schema:
|
521
617
|
#
|
522
618
|
# class Author < ActiveRecord::Base
|
@@ -533,7 +629,7 @@ module ActiveRecord
|
|
533
629
|
# @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to
|
534
630
|
# @author.books # selects all books by using the Authorship join model
|
535
631
|
#
|
536
|
-
# You can also go through a
|
632
|
+
# You can also go through a #has_many association on the join model:
|
537
633
|
#
|
538
634
|
# class Firm < ActiveRecord::Base
|
539
635
|
# has_many :clients
|
@@ -553,7 +649,7 @@ module ActiveRecord
|
|
553
649
|
# @firm.clients.flat_map { |c| c.invoices } # select all invoices for all clients of the firm
|
554
650
|
# @firm.invoices # selects all invoices by going through the Client join model
|
555
651
|
#
|
556
|
-
# Similarly you can go through a
|
652
|
+
# Similarly you can go through a #has_one association on the join model:
|
557
653
|
#
|
558
654
|
# class Group < ActiveRecord::Base
|
559
655
|
# has_many :users
|
@@ -573,7 +669,7 @@ module ActiveRecord
|
|
573
669
|
# @group.users.collect { |u| u.avatar }.compact # select all avatars for all users in the group
|
574
670
|
# @group.avatars # selects all avatars by going through the User join model.
|
575
671
|
#
|
576
|
-
# An important caveat with going through
|
672
|
+
# An important caveat with going through #has_one or #has_many associations on the
|
577
673
|
# join model is that these associations are *read-only*. For example, the following
|
578
674
|
# would not work following the previous example:
|
579
675
|
#
|
@@ -582,26 +678,26 @@ module ActiveRecord
|
|
582
678
|
#
|
583
679
|
# == Setting Inverses
|
584
680
|
#
|
585
|
-
# If you are using a
|
586
|
-
# <tt>:inverse_of</tt> option on the
|
587
|
-
# works correctly (where <tt>tags</tt> is a
|
681
|
+
# If you are using a #belongs_to on the join model, it is a good idea to set the
|
682
|
+
# <tt>:inverse_of</tt> option on the #belongs_to, which will mean that the following example
|
683
|
+
# works correctly (where <tt>tags</tt> is a #has_many <tt>:through</tt> association):
|
588
684
|
#
|
589
685
|
# @post = Post.first
|
590
686
|
# @tag = @post.tags.build name: "ruby"
|
591
687
|
# @tag.save
|
592
688
|
#
|
593
|
-
# The last line ought to save the through record (a <tt>
|
689
|
+
# The last line ought to save the through record (a <tt>Tagging</tt>). This will only work if the
|
594
690
|
# <tt>:inverse_of</tt> is set:
|
595
691
|
#
|
596
|
-
# class
|
692
|
+
# class Tagging < ActiveRecord::Base
|
597
693
|
# belongs_to :post
|
598
694
|
# belongs_to :tag, inverse_of: :taggings
|
599
695
|
# end
|
600
696
|
#
|
601
697
|
# If you do not set the <tt>:inverse_of</tt> record, the association will
|
602
698
|
# do its best to match itself up with the correct inverse. Automatic
|
603
|
-
# inverse detection only works on
|
604
|
-
#
|
699
|
+
# inverse detection only works on #has_many, #has_one, and
|
700
|
+
# #belongs_to associations.
|
605
701
|
#
|
606
702
|
# Extra options on the associations, as defined in the
|
607
703
|
# <tt>AssociationReflection::INVALID_AUTOMATIC_INVERSE_OPTIONS</tt> constant, will
|
@@ -614,7 +710,7 @@ module ActiveRecord
|
|
614
710
|
# You can turn off the automatic detection of inverse associations by setting
|
615
711
|
# the <tt>:inverse_of</tt> option to <tt>false</tt> like so:
|
616
712
|
#
|
617
|
-
# class
|
713
|
+
# class Tagging < ActiveRecord::Base
|
618
714
|
# belongs_to :tag, inverse_of: false
|
619
715
|
# end
|
620
716
|
#
|
@@ -664,7 +760,7 @@ module ActiveRecord
|
|
664
760
|
# == Polymorphic \Associations
|
665
761
|
#
|
666
762
|
# Polymorphic associations on models are not restricted on what types of models they
|
667
|
-
# can be associated with. Rather, they specify an interface that a
|
763
|
+
# can be associated with. Rather, they specify an interface that a #has_many association
|
668
764
|
# must adhere to.
|
669
765
|
#
|
670
766
|
# class Asset < ActiveRecord::Base
|
@@ -748,7 +844,7 @@ module ActiveRecord
|
|
748
844
|
#
|
749
845
|
# Post.includes(:author).each do |post|
|
750
846
|
#
|
751
|
-
# This references the name of the
|
847
|
+
# This references the name of the #belongs_to association that also used the <tt>:author</tt>
|
752
848
|
# symbol. After loading the posts, find will collect the +author_id+ from each one and load
|
753
849
|
# all the referenced authors with one query. Doing so will cut down the number of queries
|
754
850
|
# from 201 to 102.
|
@@ -759,7 +855,7 @@ module ActiveRecord
|
|
759
855
|
#
|
760
856
|
# This will load all comments with a single query. This reduces the total number of queries
|
761
857
|
# to 3. In general, the number of queries will be 1 plus the number of associations
|
762
|
-
# named (except if some of the associations are polymorphic
|
858
|
+
# named (except if some of the associations are polymorphic #belongs_to - see below).
|
763
859
|
#
|
764
860
|
# To include a deep hierarchy of associations, use a hash:
|
765
861
|
#
|
@@ -799,7 +895,7 @@ module ActiveRecord
|
|
799
895
|
# In this case it is usually more natural to include an association which has conditions defined on it:
|
800
896
|
#
|
801
897
|
# class Post < ActiveRecord::Base
|
802
|
-
# has_many :approved_comments, -> { where
|
898
|
+
# has_many :approved_comments, -> { where(approved: true) }, class_name: 'Comment'
|
803
899
|
# end
|
804
900
|
#
|
805
901
|
# Post.includes(:approved_comments)
|
@@ -831,7 +927,7 @@ module ActiveRecord
|
|
831
927
|
# For example if all the addressables are either of class Person or Company then a total
|
832
928
|
# of 3 queries will be executed. The list of addressable types to load is determined on
|
833
929
|
# the back of the addresses loaded. This is not supported if Active Record has to fallback
|
834
|
-
# to the previous implementation of eager loading and will raise
|
930
|
+
# to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError.
|
835
931
|
# The reason is that the parent model's type is a column value so its corresponding table
|
836
932
|
# name cannot be put in the +FROM+/+JOIN+ clauses of that query.
|
837
933
|
#
|
@@ -873,7 +969,7 @@ module ActiveRecord
|
|
873
969
|
# INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
874
970
|
# INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
|
875
971
|
#
|
876
|
-
# If you wish to specify your own custom joins using
|
972
|
+
# If you wish to specify your own custom joins using ActiveRecord::QueryMethods#joins method, those table
|
877
973
|
# names will take precedence over the eager associations:
|
878
974
|
#
|
879
975
|
# Post.joins(:comments).joins("inner join comments ...")
|
@@ -938,20 +1034,16 @@ module ActiveRecord
|
|
938
1034
|
# The +traps+ association on +Dungeon+ and the +dungeon+ association on +Trap+ are
|
939
1035
|
# the inverse of each other and the inverse of the +dungeon+ association on +EvilWizard+
|
940
1036
|
# is the +evil_wizard+ association on +Dungeon+ (and vice-versa). By default,
|
941
|
-
# Active Record
|
942
|
-
#
|
1037
|
+
# Active Record can guess the inverse of the association based on the name
|
1038
|
+
# of the class. The result is the following:
|
943
1039
|
#
|
944
1040
|
# d = Dungeon.first
|
945
1041
|
# t = d.traps.first
|
946
|
-
# d.
|
947
|
-
# d.level = 10
|
948
|
-
# d.level == t.dungeon.level # => false
|
1042
|
+
# d.object_id == t.dungeon.object_id # => true
|
949
1043
|
#
|
950
1044
|
# The +Dungeon+ instances +d+ and <tt>t.dungeon</tt> in the above example refer to
|
951
|
-
# the same
|
952
|
-
#
|
953
|
-
# Active Record about inverse relationships and it will optimise object loading. For
|
954
|
-
# example, if we changed our model definitions to:
|
1045
|
+
# the same in-memory instance since the association matches the name of the class.
|
1046
|
+
# The result would be the same if we added +:inverse_of+ to our model definitions:
|
955
1047
|
#
|
956
1048
|
# class Dungeon < ActiveRecord::Base
|
957
1049
|
# has_many :traps, inverse_of: :dungeon
|
@@ -966,20 +1058,19 @@ module ActiveRecord
|
|
966
1058
|
# belongs_to :dungeon, inverse_of: :evil_wizard
|
967
1059
|
# end
|
968
1060
|
#
|
969
|
-
# Then, from our code snippet above, +d+ and <tt>t.dungeon</tt> are actually the same
|
970
|
-
# in-memory instance and our final <tt>d.level == t.dungeon.level</tt> will return +true+.
|
971
|
-
#
|
972
1061
|
# There are limitations to <tt>:inverse_of</tt> support:
|
973
1062
|
#
|
974
1063
|
# * does not work with <tt>:through</tt> associations.
|
975
1064
|
# * does not work with <tt>:polymorphic</tt> associations.
|
976
|
-
# * for
|
1065
|
+
# * for #belongs_to associations #has_many inverse associations are ignored.
|
1066
|
+
#
|
1067
|
+
# For more information, see the documentation for the +:inverse_of+ option.
|
977
1068
|
#
|
978
1069
|
# == Deleting from associations
|
979
1070
|
#
|
980
1071
|
# === Dependent associations
|
981
1072
|
#
|
982
|
-
#
|
1073
|
+
# #has_many, #has_one and #belongs_to associations support the <tt>:dependent</tt> option.
|
983
1074
|
# This allows you to specify that associated records should be deleted when the owner is
|
984
1075
|
# deleted.
|
985
1076
|
#
|
@@ -1000,20 +1091,22 @@ module ActiveRecord
|
|
1000
1091
|
# callbacks declared either before or after the <tt>:dependent</tt> option
|
1001
1092
|
# can affect what it does.
|
1002
1093
|
#
|
1094
|
+
# Note that <tt>:dependent</tt> option is ignored for #has_one <tt>:through</tt> associations.
|
1095
|
+
#
|
1003
1096
|
# === Delete or destroy?
|
1004
1097
|
#
|
1005
|
-
#
|
1098
|
+
# #has_many and #has_and_belongs_to_many associations have the methods <tt>destroy</tt>,
|
1006
1099
|
# <tt>delete</tt>, <tt>destroy_all</tt> and <tt>delete_all</tt>.
|
1007
1100
|
#
|
1008
|
-
# For
|
1101
|
+
# For #has_and_belongs_to_many, <tt>delete</tt> and <tt>destroy</tt> are the same: they
|
1009
1102
|
# cause the records in the join table to be removed.
|
1010
1103
|
#
|
1011
|
-
# For
|
1104
|
+
# For #has_many, <tt>destroy</tt> and <tt>destroy_all</tt> will always call the <tt>destroy</tt> method of the
|
1012
1105
|
# record(s) being removed so that callbacks are run. However <tt>delete</tt> and <tt>delete_all</tt> will either
|
1013
1106
|
# do the deletion according to the strategy specified by the <tt>:dependent</tt> option, or
|
1014
1107
|
# if no <tt>:dependent</tt> option is given, then it will follow the default strategy.
|
1015
1108
|
# The default strategy is to do nothing (leave the foreign keys with the parent ids set), except for
|
1016
|
-
#
|
1109
|
+
# #has_many <tt>:through</tt>, where the default strategy is <tt>delete_all</tt> (delete
|
1017
1110
|
# the join records, without running their callbacks).
|
1018
1111
|
#
|
1019
1112
|
# There is also a <tt>clear</tt> method which is the same as <tt>delete_all</tt>, except that
|
@@ -1021,13 +1114,13 @@ module ActiveRecord
|
|
1021
1114
|
#
|
1022
1115
|
# === What gets deleted?
|
1023
1116
|
#
|
1024
|
-
# There is a potential pitfall here:
|
1117
|
+
# There is a potential pitfall here: #has_and_belongs_to_many and #has_many <tt>:through</tt>
|
1025
1118
|
# associations have records in join tables, as well as the associated records. So when we
|
1026
1119
|
# call one of these deletion methods, what exactly should be deleted?
|
1027
1120
|
#
|
1028
1121
|
# The answer is that it is assumed that deletion on an association is about removing the
|
1029
1122
|
# <i>link</i> between the owner and the associated object(s), rather than necessarily the
|
1030
|
-
# associated objects themselves. So with
|
1123
|
+
# associated objects themselves. So with #has_and_belongs_to_many and #has_many
|
1031
1124
|
# <tt>:through</tt>, the join records will be deleted, but the associated records won't.
|
1032
1125
|
#
|
1033
1126
|
# This makes sense if you think about it: if you were to call <tt>post.tags.delete(Tag.find_by(name: 'food'))</tt>
|
@@ -1038,20 +1131,20 @@ module ActiveRecord
|
|
1038
1131
|
# a person has many projects, and each project has many tasks. If we deleted one of a person's
|
1039
1132
|
# tasks, we would probably not want the project to be deleted. In this scenario, the delete method
|
1040
1133
|
# won't actually work: it can only be used if the association on the join model is a
|
1041
|
-
#
|
1134
|
+
# #belongs_to. In other situations you are expected to perform operations directly on
|
1042
1135
|
# either the associated records or the <tt>:through</tt> association.
|
1043
1136
|
#
|
1044
|
-
# With a regular
|
1137
|
+
# With a regular #has_many there is no distinction between the "associated records"
|
1045
1138
|
# and the "link", so there is only one choice for what gets deleted.
|
1046
1139
|
#
|
1047
|
-
# With
|
1140
|
+
# With #has_and_belongs_to_many and #has_many <tt>:through</tt>, if you want to delete the
|
1048
1141
|
# associated records themselves, you can always do something along the lines of
|
1049
1142
|
# <tt>person.tasks.each(&:destroy)</tt>.
|
1050
1143
|
#
|
1051
|
-
# == Type safety with
|
1144
|
+
# == Type safety with ActiveRecord::AssociationTypeMismatch
|
1052
1145
|
#
|
1053
1146
|
# If you attempt to assign an object to an association that doesn't match the inferred
|
1054
|
-
# or specified <tt>:class_name</tt>, you'll get an
|
1147
|
+
# or specified <tt>:class_name</tt>, you'll get an ActiveRecord::AssociationTypeMismatch.
|
1055
1148
|
#
|
1056
1149
|
# == Options
|
1057
1150
|
#
|
@@ -1071,6 +1164,7 @@ module ActiveRecord
|
|
1071
1164
|
# Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
|
1072
1165
|
# Note that this operation instantly fires update SQL without waiting for the save or update call on the
|
1073
1166
|
# parent object, unless the parent object is a new record.
|
1167
|
+
# This will also run validations and callbacks of associated object(s).
|
1074
1168
|
# [collection.delete(object, ...)]
|
1075
1169
|
# Removes one or more objects from the collection by setting their foreign keys to +NULL+.
|
1076
1170
|
# Objects will be in addition destroyed if they're associated with <tt>dependent: :destroy</tt>,
|
@@ -1088,7 +1182,8 @@ module ActiveRecord
|
|
1088
1182
|
# [collection=objects]
|
1089
1183
|
# Replaces the collections content by deleting and adding objects as appropriate. If the <tt>:through</tt>
|
1090
1184
|
# option is true callbacks in the join models are triggered except destroy callbacks, since deletion is
|
1091
|
-
# direct.
|
1185
|
+
# direct by default. You can specify <tt>dependent: :destroy</tt> or
|
1186
|
+
# <tt>dependent: :nullify</tt> to override this.
|
1092
1187
|
# [collection_singular_ids]
|
1093
1188
|
# Returns an array of the associated objects' ids
|
1094
1189
|
# [collection_singular_ids=ids]
|
@@ -1105,10 +1200,10 @@ module ActiveRecord
|
|
1105
1200
|
# [collection.size]
|
1106
1201
|
# Returns the number of associated objects.
|
1107
1202
|
# [collection.find(...)]
|
1108
|
-
# Finds an associated object according to the same rules as
|
1203
|
+
# Finds an associated object according to the same rules as ActiveRecord::FinderMethods#find.
|
1109
1204
|
# [collection.exists?(...)]
|
1110
1205
|
# Checks whether an associated object with the given conditions exists.
|
1111
|
-
# Uses the same rules as
|
1206
|
+
# Uses the same rules as ActiveRecord::FinderMethods#exists?.
|
1112
1207
|
# [collection.build(attributes = {}, ...)]
|
1113
1208
|
# Returns one or more new objects of the collection type that have been instantiated
|
1114
1209
|
# with +attributes+ and linked to this object through a foreign key, but have not yet
|
@@ -1119,7 +1214,7 @@ module ActiveRecord
|
|
1119
1214
|
# been saved (if it passed the validation). *Note*: This only works if the base model
|
1120
1215
|
# already exists in the DB, not if it is a new (unsaved) record!
|
1121
1216
|
# [collection.create!(attributes = {})]
|
1122
|
-
# Does the same as <tt>collection.create</tt>, but raises
|
1217
|
+
# Does the same as <tt>collection.create</tt>, but raises ActiveRecord::RecordInvalid
|
1123
1218
|
# if the record is invalid.
|
1124
1219
|
#
|
1125
1220
|
# === Example
|
@@ -1171,11 +1266,11 @@ module ActiveRecord
|
|
1171
1266
|
# [:class_name]
|
1172
1267
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
1173
1268
|
# from the association name. So <tt>has_many :products</tt> will by default be linked
|
1174
|
-
# to the Product class, but if the real class name is SpecialProduct
|
1269
|
+
# to the +Product+ class, but if the real class name is +SpecialProduct+, you'll have to
|
1175
1270
|
# specify it with this option.
|
1176
1271
|
# [:foreign_key]
|
1177
1272
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1178
|
-
# of this class in lower-case and "_id" suffixed. So a Person class that makes a
|
1273
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_many
|
1179
1274
|
# association will use "person_id" as the default <tt>:foreign_key</tt>.
|
1180
1275
|
# [:foreign_type]
|
1181
1276
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
@@ -1199,20 +1294,20 @@ module ActiveRecord
|
|
1199
1294
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
|
1200
1295
|
#
|
1201
1296
|
# If using with the <tt>:through</tt> option, the association on the join model must be
|
1202
|
-
# a
|
1297
|
+
# a #belongs_to, and the records which get deleted are the join records, rather than
|
1203
1298
|
# the associated records.
|
1204
1299
|
# [:counter_cache]
|
1205
1300
|
# This option can be used to configure a custom named <tt>:counter_cache.</tt> You only need this option,
|
1206
|
-
# when you customized the name of your <tt>:counter_cache</tt> on the
|
1301
|
+
# when you customized the name of your <tt>:counter_cache</tt> on the #belongs_to association.
|
1207
1302
|
# [:as]
|
1208
|
-
# Specifies a polymorphic interface (See
|
1303
|
+
# Specifies a polymorphic interface (See #belongs_to).
|
1209
1304
|
# [:through]
|
1210
1305
|
# Specifies an association through which to perform the query. This can be any other type
|
1211
1306
|
# of association, including other <tt>:through</tt> associations. Options for <tt>:class_name</tt>,
|
1212
1307
|
# <tt>:primary_key</tt> and <tt>:foreign_key</tt> are ignored, as the association uses the
|
1213
1308
|
# source reflection.
|
1214
1309
|
#
|
1215
|
-
# If the association on the join model is a
|
1310
|
+
# If the association on the join model is a #belongs_to, the collection can be modified
|
1216
1311
|
# and the records on the <tt>:through</tt> model will be automatically created and removed
|
1217
1312
|
# as appropriate. Otherwise, the collection is read-only, so you should manipulate the
|
1218
1313
|
# <tt>:through</tt> association directly.
|
@@ -1223,15 +1318,16 @@ module ActiveRecord
|
|
1223
1318
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1224
1319
|
# section above.)
|
1225
1320
|
# [:source]
|
1226
|
-
# Specifies the source association name used by <tt
|
1321
|
+
# Specifies the source association name used by #has_many <tt>:through</tt> queries.
|
1227
1322
|
# Only use it if the name cannot be inferred from the association.
|
1228
1323
|
# <tt>has_many :subscribers, through: :subscriptions</tt> will look for either <tt>:subscribers</tt> or
|
1229
1324
|
# <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
|
1230
1325
|
# [:source_type]
|
1231
|
-
# Specifies type of the source association used by <tt
|
1232
|
-
# association is a polymorphic
|
1326
|
+
# Specifies type of the source association used by #has_many <tt>:through</tt> queries where the source
|
1327
|
+
# association is a polymorphic #belongs_to.
|
1233
1328
|
# [:validate]
|
1234
|
-
#
|
1329
|
+
# When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
|
1330
|
+
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1235
1331
|
# [:autosave]
|
1236
1332
|
# If true, always save the associated objects or destroy them if marked for destruction,
|
1237
1333
|
# when saving the parent object. If false, never save or destroy the associated objects.
|
@@ -1239,18 +1335,23 @@ module ActiveRecord
|
|
1239
1335
|
# +before_save+ callback. Because callbacks are run in the order they are defined, associated objects
|
1240
1336
|
# may need to be explicitly saved in any user-defined +before_save+ callbacks.
|
1241
1337
|
#
|
1242
|
-
# Note that
|
1338
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1339
|
+
# <tt>:autosave</tt> to <tt>true</tt>.
|
1243
1340
|
# [:inverse_of]
|
1244
|
-
# Specifies the name of the
|
1245
|
-
# that is the inverse of this
|
1341
|
+
# Specifies the name of the #belongs_to association on the associated object
|
1342
|
+
# that is the inverse of this #has_many association. Does not work in combination
|
1246
1343
|
# with <tt>:through</tt> or <tt>:as</tt> options.
|
1247
1344
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1345
|
+
# [:extend]
|
1346
|
+
# Specifies a module or array of modules that will be extended into the association object returned.
|
1347
|
+
# Useful for defining methods on associations, especially when they should be shared between multiple
|
1348
|
+
# association objects.
|
1248
1349
|
#
|
1249
1350
|
# Option examples:
|
1250
|
-
# has_many :comments, -> { order
|
1251
|
-
# has_many :comments, -> { includes
|
1351
|
+
# has_many :comments, -> { order("posted_on") }
|
1352
|
+
# has_many :comments, -> { includes(:author) }
|
1252
1353
|
# has_many :people, -> { where(deleted: false).order("name") }, class_name: "Person"
|
1253
|
-
# has_many :tracks, -> { order
|
1354
|
+
# has_many :tracks, -> { order("position") }, dependent: :destroy
|
1254
1355
|
# has_many :comments, dependent: :nullify
|
1255
1356
|
# has_many :tags, as: :taggable
|
1256
1357
|
# has_many :reports, -> { readonly }
|
@@ -1262,8 +1363,8 @@ module ActiveRecord
|
|
1262
1363
|
|
1263
1364
|
# Specifies a one-to-one association with another class. This method should only be used
|
1264
1365
|
# if the other class contains the foreign key. If the current class contains the foreign key,
|
1265
|
-
# then you should use
|
1266
|
-
# on when to use
|
1366
|
+
# then you should use #belongs_to instead. See also ActiveRecord::Associations::ClassMethods's overview
|
1367
|
+
# on when to use #has_one and when to use #belongs_to.
|
1267
1368
|
#
|
1268
1369
|
# The following methods for retrieval and query of a single associated object will be added:
|
1269
1370
|
#
|
@@ -1285,7 +1386,7 @@ module ActiveRecord
|
|
1285
1386
|
# with +attributes+, linked to this object through a foreign key, and that
|
1286
1387
|
# has already been saved (if it passed the validation).
|
1287
1388
|
# [create_association!(attributes = {})]
|
1288
|
-
# Does the same as <tt>create_association</tt>, but raises
|
1389
|
+
# Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
|
1289
1390
|
# if the record is invalid.
|
1290
1391
|
#
|
1291
1392
|
# === Example
|
@@ -1326,9 +1427,11 @@ module ActiveRecord
|
|
1326
1427
|
# * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Callbacks are not executed.
|
1327
1428
|
# * <tt>:restrict_with_exception</tt> causes an exception to be raised if there is an associated record
|
1328
1429
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
|
1430
|
+
#
|
1431
|
+
# Note that <tt>:dependent</tt> option is ignored when using <tt>:through</tt> option.
|
1329
1432
|
# [:foreign_key]
|
1330
1433
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1331
|
-
# of this class in lower-case and "_id" suffixed. So a Person class that makes a
|
1434
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_one association
|
1332
1435
|
# will use "person_id" as the default <tt>:foreign_key</tt>.
|
1333
1436
|
# [:foreign_type]
|
1334
1437
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
@@ -1339,31 +1442,33 @@ module ActiveRecord
|
|
1339
1442
|
# [:primary_key]
|
1340
1443
|
# Specify the method that returns the primary key used for the association. By default this is +id+.
|
1341
1444
|
# [:as]
|
1342
|
-
# Specifies a polymorphic interface (See
|
1445
|
+
# Specifies a polymorphic interface (See #belongs_to).
|
1343
1446
|
# [:through]
|
1344
1447
|
# Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>,
|
1345
1448
|
# <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
|
1346
|
-
# source reflection. You can only use a <tt>:through</tt> query through a
|
1347
|
-
# or
|
1449
|
+
# source reflection. You can only use a <tt>:through</tt> query through a #has_one
|
1450
|
+
# or #belongs_to association on the join model.
|
1348
1451
|
# [:source]
|
1349
|
-
# Specifies the source association name used by <tt
|
1452
|
+
# Specifies the source association name used by #has_one <tt>:through</tt> queries.
|
1350
1453
|
# Only use it if the name cannot be inferred from the association.
|
1351
1454
|
# <tt>has_one :favorite, through: :favorites</tt> will look for a
|
1352
1455
|
# <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
|
1353
1456
|
# [:source_type]
|
1354
|
-
# Specifies type of the source association used by <tt
|
1355
|
-
# association is a polymorphic
|
1457
|
+
# Specifies type of the source association used by #has_one <tt>:through</tt> queries where the source
|
1458
|
+
# association is a polymorphic #belongs_to.
|
1356
1459
|
# [:validate]
|
1357
|
-
#
|
1460
|
+
# When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
|
1461
|
+
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1358
1462
|
# [:autosave]
|
1359
1463
|
# If true, always save the associated object or destroy it if marked for destruction,
|
1360
1464
|
# when saving the parent object. If false, never save or destroy the associated object.
|
1361
1465
|
# By default, only save the associated object if it's a new record.
|
1362
1466
|
#
|
1363
|
-
# Note that
|
1467
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1468
|
+
# <tt>:autosave</tt> to <tt>true</tt>.
|
1364
1469
|
# [:inverse_of]
|
1365
|
-
# Specifies the name of the
|
1366
|
-
# that is the inverse of this
|
1470
|
+
# Specifies the name of the #belongs_to association on the associated object
|
1471
|
+
# that is the inverse of this #has_one association. Does not work in combination
|
1367
1472
|
# with <tt>:through</tt> or <tt>:as</tt> options.
|
1368
1473
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1369
1474
|
# [:required]
|
@@ -1375,12 +1480,12 @@ module ActiveRecord
|
|
1375
1480
|
# has_one :credit_card, dependent: :destroy # destroys the associated credit card
|
1376
1481
|
# has_one :credit_card, dependent: :nullify # updates the associated records foreign
|
1377
1482
|
# # key value to NULL rather than destroying it
|
1378
|
-
# has_one :last_comment, -> { order
|
1379
|
-
# has_one :project_manager, -> { where
|
1483
|
+
# has_one :last_comment, -> { order('posted_on') }, class_name: "Comment"
|
1484
|
+
# has_one :project_manager, -> { where(role: 'project_manager') }, class_name: "Person"
|
1380
1485
|
# has_one :attachment, as: :attachable
|
1381
1486
|
# has_one :boss, -> { readonly }
|
1382
1487
|
# has_one :club, through: :membership
|
1383
|
-
# has_one :primary_address, -> { where
|
1488
|
+
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
1384
1489
|
# has_one :credit_card, required: true
|
1385
1490
|
def has_one(name, scope = nil, options = {})
|
1386
1491
|
reflection = Builder::HasOne.build(self, name, scope, options)
|
@@ -1389,8 +1494,8 @@ module ActiveRecord
|
|
1389
1494
|
|
1390
1495
|
# Specifies a one-to-one association with another class. This method should only be used
|
1391
1496
|
# if this class contains the foreign key. If the other class contains the foreign key,
|
1392
|
-
# then you should use
|
1393
|
-
# on when to use
|
1497
|
+
# then you should use #has_one instead. See also ActiveRecord::Associations::ClassMethods's overview
|
1498
|
+
# on when to use #has_one and when to use #belongs_to.
|
1394
1499
|
#
|
1395
1500
|
# Methods will be added for retrieval and query for a single associated object, for which
|
1396
1501
|
# this object holds an id:
|
@@ -1410,7 +1515,7 @@ module ActiveRecord
|
|
1410
1515
|
# with +attributes+, linked to this object through a foreign key, and that
|
1411
1516
|
# has already been saved (if it passed the validation).
|
1412
1517
|
# [create_association!(attributes = {})]
|
1413
|
-
# Does the same as <tt>create_association</tt>, but raises
|
1518
|
+
# Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
|
1414
1519
|
# if the record is invalid.
|
1415
1520
|
#
|
1416
1521
|
# === Example
|
@@ -1430,7 +1535,7 @@ module ActiveRecord
|
|
1430
1535
|
# when you access the associated object.
|
1431
1536
|
#
|
1432
1537
|
# Scope examples:
|
1433
|
-
# belongs_to :
|
1538
|
+
# belongs_to :firm, -> { where(id: 2) }
|
1434
1539
|
# belongs_to :user, -> { joins(:friends) }
|
1435
1540
|
# belongs_to :level, ->(level) { where("game_level > ?", level.current) }
|
1436
1541
|
#
|
@@ -1457,12 +1562,12 @@ module ActiveRecord
|
|
1457
1562
|
# [:dependent]
|
1458
1563
|
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
|
1459
1564
|
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
|
1460
|
-
# This option should not be specified when
|
1461
|
-
# a
|
1565
|
+
# This option should not be specified when #belongs_to is used in conjunction with
|
1566
|
+
# a #has_many relationship on another class because of the potential to leave
|
1462
1567
|
# orphaned records behind.
|
1463
1568
|
# [:counter_cache]
|
1464
|
-
# Caches the number of belonging objects on the associate class through the use of
|
1465
|
-
# and
|
1569
|
+
# Caches the number of belonging objects on the associate class through the use of CounterCache::ClassMethods#increment_counter
|
1570
|
+
# and CounterCache::ClassMethods#decrement_counter. The counter cache is incremented when an object of this
|
1466
1571
|
# class is created and decremented when it's destroyed. This requires that a column
|
1467
1572
|
# named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
|
1468
1573
|
# is used on the associate class (such as a Post class) - that is the migration for
|
@@ -1477,27 +1582,35 @@ module ActiveRecord
|
|
1477
1582
|
# Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
|
1478
1583
|
# to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
|
1479
1584
|
# [:validate]
|
1480
|
-
#
|
1585
|
+
# When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
|
1586
|
+
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1481
1587
|
# [:autosave]
|
1482
1588
|
# If true, always save the associated object or destroy it if marked for destruction, when
|
1483
1589
|
# saving the parent object.
|
1484
1590
|
# If false, never save or destroy the associated object.
|
1485
1591
|
# By default, only save the associated object if it's a new record.
|
1486
1592
|
#
|
1487
|
-
# Note that
|
1593
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for
|
1594
|
+
# sets <tt>:autosave</tt> to <tt>true</tt>.
|
1488
1595
|
# [:touch]
|
1489
1596
|
# If true, the associated object will be touched (the updated_at/on attributes set to current time)
|
1490
1597
|
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
1491
1598
|
# will be updated with the current time in addition to the updated_at/on attribute.
|
1599
|
+
# Please note that with touching no validation is performed and only the +after_touch+,
|
1600
|
+
# +after_commit+ and +after_rollback+ callbacks are executed.
|
1492
1601
|
# [:inverse_of]
|
1493
|
-
# Specifies the name of the
|
1494
|
-
# object that is the inverse of this
|
1602
|
+
# Specifies the name of the #has_one or #has_many association on the associated
|
1603
|
+
# object that is the inverse of this #belongs_to association. Does not work in
|
1495
1604
|
# combination with the <tt>:polymorphic</tt> options.
|
1496
1605
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1606
|
+
# [:optional]
|
1607
|
+
# When set to +true+, the association will not have its presence validated.
|
1497
1608
|
# [:required]
|
1498
1609
|
# When set to +true+, the association will also have its presence validated.
|
1499
1610
|
# This will validate the association itself, not the id. You can use
|
1500
1611
|
# +:inverse_of+ to avoid an extra query during validation.
|
1612
|
+
# NOTE: <tt>required</tt> is set to <tt>true</tt> by default and is deprecated. If
|
1613
|
+
# you don't want to have association presence validated, use <tt>optional: true</tt>.
|
1501
1614
|
#
|
1502
1615
|
# Option examples:
|
1503
1616
|
# belongs_to :firm, foreign_key: "client_of"
|
@@ -1508,9 +1621,9 @@ module ActiveRecord
|
|
1508
1621
|
# belongs_to :attachable, polymorphic: true
|
1509
1622
|
# belongs_to :project, -> { readonly }
|
1510
1623
|
# belongs_to :post, counter_cache: true
|
1511
|
-
# belongs_to :
|
1624
|
+
# belongs_to :comment, touch: true
|
1512
1625
|
# belongs_to :company, touch: :employees_last_updated_at
|
1513
|
-
# belongs_to :
|
1626
|
+
# belongs_to :user, optional: true
|
1514
1627
|
def belongs_to(name, scope = nil, options = {})
|
1515
1628
|
reflection = Builder::BelongsTo.build(self, name, scope, options)
|
1516
1629
|
Reflection.add_reflection self, name, reflection
|
@@ -1533,12 +1646,9 @@ module ActiveRecord
|
|
1533
1646
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1534
1647
|
# join table with a migration such as this:
|
1535
1648
|
#
|
1536
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration
|
1649
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[5.0]
|
1537
1650
|
# def change
|
1538
|
-
#
|
1539
|
-
# t.integer :developer_id
|
1540
|
-
# t.integer :project_id
|
1541
|
-
# end
|
1651
|
+
# create_join_table :developers, :projects
|
1542
1652
|
# end
|
1543
1653
|
# end
|
1544
1654
|
#
|
@@ -1580,10 +1690,10 @@ module ActiveRecord
|
|
1580
1690
|
# [collection.find(id)]
|
1581
1691
|
# Finds an associated object responding to the +id+ and that
|
1582
1692
|
# meets the condition that it has to be associated with this object.
|
1583
|
-
# Uses the same rules as
|
1693
|
+
# Uses the same rules as ActiveRecord::FinderMethods#find.
|
1584
1694
|
# [collection.exists?(...)]
|
1585
1695
|
# Checks whether an associated object with the given conditions exists.
|
1586
|
-
# Uses the same rules as
|
1696
|
+
# Uses the same rules as ActiveRecord::FinderMethods#exists?.
|
1587
1697
|
# [collection.build(attributes = {})]
|
1588
1698
|
# Returns a new object of the collection type that has been instantiated
|
1589
1699
|
# with +attributes+ and linked to this object through the join table, but has not yet been saved.
|
@@ -1618,7 +1728,7 @@ module ActiveRecord
|
|
1618
1728
|
# query when you access the associated collection.
|
1619
1729
|
#
|
1620
1730
|
# Scope examples:
|
1621
|
-
# has_and_belongs_to_many :projects, -> { includes
|
1731
|
+
# has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
|
1622
1732
|
# has_and_belongs_to_many :categories, ->(category) {
|
1623
1733
|
# where("default_category = ?", category.name)
|
1624
1734
|
# }
|
@@ -1647,32 +1757,32 @@ module ActiveRecord
|
|
1647
1757
|
# [:join_table]
|
1648
1758
|
# Specify the name of the join table if the default based on lexical order isn't what you want.
|
1649
1759
|
# <b>WARNING:</b> If you're overwriting the table name of either class, the +table_name+ method
|
1650
|
-
# MUST be declared underneath any
|
1760
|
+
# MUST be declared underneath any #has_and_belongs_to_many declaration in order to work.
|
1651
1761
|
# [:foreign_key]
|
1652
1762
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1653
1763
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes
|
1654
|
-
# a
|
1764
|
+
# a #has_and_belongs_to_many association to Project will use "person_id" as the
|
1655
1765
|
# default <tt>:foreign_key</tt>.
|
1656
1766
|
# [:association_foreign_key]
|
1657
1767
|
# Specify the foreign key used for the association on the receiving side of the association.
|
1658
1768
|
# By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
|
1659
|
-
# So if a Person class makes a
|
1769
|
+
# So if a Person class makes a #has_and_belongs_to_many association to Project,
|
1660
1770
|
# the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
|
1661
|
-
# [:readonly]
|
1662
|
-
# If true, all the associated objects are readonly through the association.
|
1663
1771
|
# [:validate]
|
1664
|
-
#
|
1772
|
+
# When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
|
1773
|
+
# If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
|
1665
1774
|
# [:autosave]
|
1666
1775
|
# If true, always save the associated objects or destroy them if marked for destruction, when
|
1667
1776
|
# saving the parent object.
|
1668
1777
|
# If false, never save or destroy the associated objects.
|
1669
1778
|
# By default, only save associated objects that are new records.
|
1670
1779
|
#
|
1671
|
-
# Note that
|
1780
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1781
|
+
# <tt>:autosave</tt> to <tt>true</tt>.
|
1672
1782
|
#
|
1673
1783
|
# Option examples:
|
1674
1784
|
# has_and_belongs_to_many :projects
|
1675
|
-
# has_and_belongs_to_many :projects, -> { includes
|
1785
|
+
# has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
|
1676
1786
|
# has_and_belongs_to_many :nations, class_name: "Country"
|
1677
1787
|
# has_and_belongs_to_many :categories, join_table: "prods_cats"
|
1678
1788
|
# has_and_belongs_to_many :categories, -> { readonly }
|
@@ -1688,16 +1798,14 @@ module ActiveRecord
|
|
1688
1798
|
|
1689
1799
|
join_model = builder.through_model
|
1690
1800
|
|
1691
|
-
# FIXME: we should move this to the internal constants. Also people
|
1692
|
-
# should never directly access this constant so I'm not happy about
|
1693
|
-
# setting it.
|
1694
1801
|
const_set join_model.name, join_model
|
1802
|
+
private_constant join_model.name
|
1695
1803
|
|
1696
1804
|
middle_reflection = builder.middle_reflection join_model
|
1697
1805
|
|
1698
1806
|
Builder::HasMany.define_callbacks self, middle_reflection
|
1699
1807
|
Reflection.add_reflection self, middle_reflection.name, middle_reflection
|
1700
|
-
middle_reflection.parent_reflection =
|
1808
|
+
middle_reflection.parent_reflection = habtm_reflection
|
1701
1809
|
|
1702
1810
|
include Module.new {
|
1703
1811
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
@@ -1718,7 +1826,7 @@ module ActiveRecord
|
|
1718
1826
|
end
|
1719
1827
|
|
1720
1828
|
has_many name, scope, hm_options, &extension
|
1721
|
-
self._reflections[name.to_s].parent_reflection =
|
1829
|
+
self._reflections[name.to_s].parent_reflection = habtm_reflection
|
1722
1830
|
end
|
1723
1831
|
end
|
1724
1832
|
end
|