activerecord 4.2.11.3 → 5.0.0.beta1
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 +5 -5
- data/CHANGELOG.md +1029 -1349
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -7
- data/examples/performance.rb +2 -2
- data/lib/active_record.rb +7 -3
- data/lib/active_record/aggregations.rb +35 -25
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations.rb +305 -204
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +10 -8
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +20 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +41 -18
- data/lib/active_record/associations/builder/collection_association.rb +8 -24
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +11 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +10 -5
- data/lib/active_record/associations/builder/singular_association.rb +2 -9
- data/lib/active_record/associations/collection_association.rb +40 -43
- data/lib/active_record/associations/collection_proxy.rb +55 -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 -52
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +28 -18
- data/lib/active_record/associations/join_dependency/join_association.rb +13 -12
- data/lib/active_record/associations/preloader.rb +13 -4
- data/lib/active_record/associations/preloader/association.rb +45 -51
- 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 +5 -4
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/attribute.rb +61 -17
- data/lib/active_record/attribute/user_provided_default.rb +23 -0
- data/lib/active_record/attribute_assignment.rb +27 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +79 -26
- 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 +26 -42
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +42 -9
- data/lib/active_record/attribute_methods/write.rb +13 -24
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attributes.rb +194 -81
- data/lib/active_record/autosave_association.rb +33 -15
- data/lib/active_record/base.rb +30 -18
- data/lib/active_record/callbacks.rb +36 -40
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +31 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +431 -122
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +40 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -8
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -38
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +229 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +52 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +275 -115
- data/lib/active_record/connection_adapters/abstract/transaction.rb +32 -33
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -32
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +384 -221
- data/lib/active_record/connection_adapters/column.rb +27 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -21
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +57 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +69 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +59 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +22 -101
- data/lib/active_record/connection_adapters/postgresql/column.rb +6 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +23 -57
- 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 +1 -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 -2
- 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 +23 -16
- 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/quoting.rb +18 -11
- 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 +54 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +174 -128
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +184 -112
- 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/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +134 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +28 -11
- data/lib/active_record/connection_handling.rb +5 -5
- data/lib/active_record/core.rb +72 -104
- data/lib/active_record/counter_cache.rb +9 -20
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +110 -76
- data/lib/active_record/errors.rb +72 -47
- 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 +19 -4
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +27 -40
- data/lib/active_record/integration.rb +4 -4
- 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 +10 -14
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +40 -22
- data/lib/active_record/migration.rb +304 -133
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +90 -0
- data/lib/active_record/model_schema.rb +92 -40
- data/lib/active_record/nested_attributes.rb +45 -34
- data/lib/active_record/null_relation.rb +15 -7
- data/lib/active_record/persistence.rb +112 -72
- data/lib/active_record/querying.rb +6 -5
- data/lib/active_record/railtie.rb +20 -13
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +47 -38
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +182 -57
- data/lib/active_record/relation.rb +152 -100
- data/lib/active_record/relation/batches.rb +133 -33
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +80 -101
- data/lib/active_record/relation/delegation.rb +6 -19
- data/lib/active_record/relation/finder_methods.rb +58 -46
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +13 -42
- data/lib/active_record/relation/predicate_builder.rb +99 -105
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +78 -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/range_handler.rb +17 -0
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +274 -238
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -6
- data/lib/active_record/relation/where_clause.rb +173 -0
- data/lib/active_record/relation/where_clause_factory.rb +37 -0
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +94 -65
- data/lib/active_record/schema.rb +23 -22
- data/lib/active_record/schema_dumper.rb +33 -22
- data/lib/active_record/schema_migration.rb +10 -4
- data/lib/active_record/scoping.rb +17 -6
- data/lib/active_record/scoping/default.rb +19 -6
- data/lib/active_record/scoping/named.rb +39 -28
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +15 -13
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +54 -0
- data/lib/active_record/table_metadata.rb +64 -0
- data/lib/active_record/tasks/database_tasks.rb +30 -40
- data/lib/active_record/tasks/mysql_database_tasks.rb +7 -15
- 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 +16 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -45
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +33 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +9 -14
- data/lib/active_record/type/time.rb +3 -21
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record/validations/absence.rb +24 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +36 -0
- data/lib/active_record/validations/presence.rb +12 -12
- data/lib/active_record/validations/uniqueness.rb +24 -21
- data/lib/rails/generators/active_record/migration.rb +7 -0
- 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 +4 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +21 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +50 -35
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- 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 -64
- 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 -110
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -26,13 +26,13 @@ The Product class is automatically mapped to the table named "products",
|
|
26
26
|
which might look like this:
|
27
27
|
|
28
28
|
CREATE TABLE products (
|
29
|
-
id int
|
29
|
+
id int NOT NULL auto_increment,
|
30
30
|
name varchar(255),
|
31
31
|
PRIMARY KEY (id)
|
32
32
|
);
|
33
33
|
|
34
|
-
This would also define the following accessors:
|
35
|
-
|
34
|
+
This would also define the following accessors: <tt>Product#name</tt> and
|
35
|
+
<tt>Product#name=(new_name)</tt>.
|
36
36
|
|
37
37
|
|
38
38
|
* Associations between objects defined by simple class methods.
|
@@ -138,7 +138,7 @@ This would also define the following accessors: `Product#name` and
|
|
138
138
|
|
139
139
|
* Database agnostic schema management with Migrations.
|
140
140
|
|
141
|
-
class AddSystemSettings < ActiveRecord::Migration
|
141
|
+
class AddSystemSettings < ActiveRecord::Migration[5.0]
|
142
142
|
def up
|
143
143
|
create_table :system_settings do |t|
|
144
144
|
t.string :name
|
@@ -188,11 +188,11 @@ Admit the Database:
|
|
188
188
|
|
189
189
|
The latest version of Active Record can be installed with RubyGems:
|
190
190
|
|
191
|
-
|
191
|
+
$ gem install activerecord
|
192
192
|
|
193
193
|
Source code can be downloaded as part of the Rails project on GitHub:
|
194
194
|
|
195
|
-
* https://github.com/rails/rails/tree/
|
195
|
+
* https://github.com/rails/rails/tree/master/activerecord
|
196
196
|
|
197
197
|
|
198
198
|
== License
|
@@ -215,4 +215,3 @@ Bug reports can be filed for the Ruby on Rails project here:
|
|
215
215
|
Feature requests should be discussed on the rails-core mailing list here:
|
216
216
|
|
217
217
|
* https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
|
218
|
-
|
data/examples/performance.rb
CHANGED
@@ -39,8 +39,8 @@ class Exhibit < ActiveRecord::Base
|
|
39
39
|
where("notes IS NOT NULL")
|
40
40
|
end
|
41
41
|
|
42
|
-
def self.look(exhibits) exhibits.each
|
43
|
-
def self.feel(exhibits) exhibits.each
|
42
|
+
def self.look(exhibits) exhibits.each(&:look) end
|
43
|
+
def self.feel(exhibits) exhibits.each(&:feel) end
|
44
44
|
end
|
45
45
|
|
46
46
|
def progress_bar(int); print "." if (int%100).zero? ; end
|
data/lib/active_record.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2004-
|
2
|
+
# Copyright (c) 2004-2015 David Heinemeier Hansson
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
# a copy of this software and associated documentation files (the
|
@@ -43,14 +43,17 @@ module ActiveRecord
|
|
43
43
|
autoload :Explain
|
44
44
|
autoload :Inheritance
|
45
45
|
autoload :Integration
|
46
|
+
autoload :LegacyYamlAdapter
|
46
47
|
autoload :Migration
|
47
48
|
autoload :Migrator, 'active_record/migration'
|
48
49
|
autoload :ModelSchema
|
49
50
|
autoload :NestedAttributes
|
50
51
|
autoload :NoTouching
|
52
|
+
autoload :TouchLater
|
51
53
|
autoload :Persistence
|
52
54
|
autoload :QueryCache
|
53
55
|
autoload :Querying
|
56
|
+
autoload :CollectionCacheKey
|
54
57
|
autoload :ReadonlyAttributes
|
55
58
|
autoload :RecordInvalid, 'active_record/validations'
|
56
59
|
autoload :Reflection
|
@@ -63,10 +66,13 @@ module ActiveRecord
|
|
63
66
|
autoload :Serialization
|
64
67
|
autoload :StatementCache
|
65
68
|
autoload :Store
|
69
|
+
autoload :Suppressor
|
70
|
+
autoload :TableMetadata
|
66
71
|
autoload :Timestamp
|
67
72
|
autoload :Transactions
|
68
73
|
autoload :Translation
|
69
74
|
autoload :Validations
|
75
|
+
autoload :SecureToken
|
70
76
|
|
71
77
|
eager_autoload do
|
72
78
|
autoload :ActiveRecordError, 'active_record/errors'
|
@@ -79,8 +85,6 @@ module ActiveRecord
|
|
79
85
|
autoload :AttributeMethods
|
80
86
|
autoload :AutosaveAssociation
|
81
87
|
|
82
|
-
autoload :LegacyYamlAdapter
|
83
|
-
|
84
88
|
autoload :Relation
|
85
89
|
autoload :AssociationRelation
|
86
90
|
autoload :NullRelation
|
@@ -1,14 +1,31 @@
|
|
1
1
|
module ActiveRecord
|
2
|
-
#
|
3
|
-
module Aggregations
|
2
|
+
# See ActiveRecord::Aggregations::ClassMethods for documentation
|
3
|
+
module Aggregations
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
def
|
7
|
-
@aggregation_cache
|
6
|
+
def initialize_dup(*) # :nodoc:
|
7
|
+
@aggregation_cache = {}
|
8
|
+
super
|
8
9
|
end
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
def reload(*) # :nodoc:
|
12
|
+
clear_aggregation_cache
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def clear_aggregation_cache # :nodoc:
|
19
|
+
@aggregation_cache.clear if persisted?
|
20
|
+
end
|
21
|
+
|
22
|
+
def init_internals # :nodoc:
|
23
|
+
@aggregation_cache = {}
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
# Active Record implements aggregation through a macro-like class method called #composed_of
|
28
|
+
# for representing attributes as value objects. It expresses relationships like "Account [is]
|
12
29
|
# composed of Money [among other things]" or "Person [is] composed of [an] address". Each call
|
13
30
|
# to the macro adds a description of how the value objects are created from the attributes of
|
14
31
|
# the entity object (when the entity is initialized either as a new object or from finding an
|
@@ -87,11 +104,6 @@ module ActiveRecord
|
|
87
104
|
# customer.address_city = "Copenhagen"
|
88
105
|
# customer.address # => Address.new("Hyancintvej", "Copenhagen")
|
89
106
|
#
|
90
|
-
# customer.address_street = "Vesterbrogade"
|
91
|
-
# customer.address # => Address.new("Hyancintvej", "Copenhagen")
|
92
|
-
# customer.clear_aggregation_cache
|
93
|
-
# customer.address # => Address.new("Vesterbrogade", "Copenhagen")
|
94
|
-
#
|
95
107
|
# customer.address = Address.new("May Street", "Chicago")
|
96
108
|
# customer.address_street # => "May Street"
|
97
109
|
# customer.address_city # => "Chicago"
|
@@ -108,12 +120,12 @@ module ActiveRecord
|
|
108
120
|
#
|
109
121
|
# It's also important to treat the value objects as immutable. Don't allow the Money object to have
|
110
122
|
# its amount changed after creation. Create a new Money object with the new value instead. The
|
111
|
-
# Money#exchange_to method is an example of this. It returns a new value object instead of changing
|
123
|
+
# <tt>Money#exchange_to</tt> method is an example of this. It returns a new value object instead of changing
|
112
124
|
# its own values. Active Record won't persist value objects that have been changed through means
|
113
125
|
# other than the writer method.
|
114
126
|
#
|
115
127
|
# The immutable requirement is enforced by Active Record by freezing any object assigned as a value
|
116
|
-
# object. Attempting to change it afterwards will result in a RuntimeError
|
128
|
+
# object. Attempting to change it afterwards will result in a +RuntimeError+.
|
117
129
|
#
|
118
130
|
# Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not
|
119
131
|
# keeping value objects immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable
|
@@ -122,17 +134,17 @@ module ActiveRecord
|
|
122
134
|
#
|
123
135
|
# By default value objects are initialized by calling the <tt>new</tt> constructor of the value
|
124
136
|
# class passing each of the mapped attributes, in the order specified by the <tt>:mapping</tt>
|
125
|
-
# option, as arguments. If the value class doesn't support this convention then
|
137
|
+
# option, as arguments. If the value class doesn't support this convention then #composed_of allows
|
126
138
|
# a custom constructor to be specified.
|
127
139
|
#
|
128
140
|
# When a new value is assigned to the value object, the default assumption is that the new value
|
129
141
|
# is an instance of the value class. Specifying a custom converter allows the new value to be automatically
|
130
142
|
# converted to an instance of value class if necessary.
|
131
143
|
#
|
132
|
-
# For example, the NetworkResource model has +network_address+ and +cidr_range+ attributes that should be
|
133
|
-
# aggregated using the NetAddr::CIDR value class (http://www.
|
144
|
+
# For example, the +NetworkResource+ model has +network_address+ and +cidr_range+ attributes that should be
|
145
|
+
# aggregated using the +NetAddr::CIDR+ value class (http://www.rubydoc.info/gems/netaddr/1.5.0/NetAddr/CIDR).
|
134
146
|
# The constructor for the value class is called +create+ and it expects a CIDR address string as a parameter.
|
135
|
-
# New values can be assigned to the value object using either another NetAddr::CIDR object, a string
|
147
|
+
# New values can be assigned to the value object using either another +NetAddr::CIDR+ object, a string
|
136
148
|
# or an array. The <tt>:constructor</tt> and <tt>:converter</tt> options can be used to meet
|
137
149
|
# these requirements:
|
138
150
|
#
|
@@ -161,7 +173,7 @@ module ActiveRecord
|
|
161
173
|
#
|
162
174
|
# == Finding records by a value object
|
163
175
|
#
|
164
|
-
# Once a
|
176
|
+
# Once a #composed_of relationship is specified for a model, records can be loaded from the database
|
165
177
|
# by specifying an instance of the value object in the conditions hash. The following example
|
166
178
|
# finds all customers with +balance_amount+ equal to 20 and +balance_currency+ equal to "USD":
|
167
179
|
#
|
@@ -174,7 +186,7 @@ module ActiveRecord
|
|
174
186
|
# Options are:
|
175
187
|
# * <tt>:class_name</tt> - Specifies the class name of the association. Use it only if that name
|
176
188
|
# can't be inferred from the part id. So <tt>composed_of :address</tt> will by default be linked
|
177
|
-
# to the Address class, but if the real class name is CompanyAddress
|
189
|
+
# to the Address class, but if the real class name is +CompanyAddress+, you'll have to specify it
|
178
190
|
# with this option.
|
179
191
|
# * <tt>:mapping</tt> - Specifies the mapping of entity attributes to attributes of the value
|
180
192
|
# object. Each mapping is represented as an array where the first item is the name of the
|
@@ -244,17 +256,15 @@ module ActiveRecord
|
|
244
256
|
def writer_method(name, class_name, mapping, allow_nil, converter)
|
245
257
|
define_method("#{name}=") do |part|
|
246
258
|
klass = class_name.constantize
|
259
|
+
if part.is_a?(Hash)
|
260
|
+
raise ArgumentError unless part.size == part.keys.max
|
261
|
+
part = klass.new(*part.sort.map(&:last))
|
262
|
+
end
|
247
263
|
|
248
264
|
unless part.is_a?(klass) || converter.nil? || part.nil?
|
249
265
|
part = converter.respond_to?(:call) ? converter.call(part) : klass.send(converter, part)
|
250
266
|
end
|
251
267
|
|
252
|
-
hash_from_multiparameter_assignment = part.is_a?(Hash) &&
|
253
|
-
part.each_key.all? { |k| k.is_a?(Integer) }
|
254
|
-
if hash_from_multiparameter_assignment
|
255
|
-
part = klass.new(*part.values)
|
256
|
-
end
|
257
|
-
|
258
268
|
if part.nil? && allow_nil
|
259
269
|
mapping.each { |key, _| self[key] = nil }
|
260
270
|
@aggregation_cache[name] = nil
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class AssociationRelation < Relation
|
3
|
-
def initialize(klass, table, association)
|
4
|
-
super(klass, table)
|
3
|
+
def initialize(klass, table, predicate_builder, association)
|
4
|
+
super(klass, table, predicate_builder)
|
5
5
|
@association = association
|
6
6
|
end
|
7
7
|
|
@@ -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
|
#
|
@@ -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>s, and you can use the
|
507
|
+
# \Associations are built from <tt>Relation</tt>s, 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
|
#
|
@@ -1088,7 +1181,8 @@ module ActiveRecord
|
|
1088
1181
|
# [collection=objects]
|
1089
1182
|
# Replaces the collections content by deleting and adding objects as appropriate. If the <tt>:through</tt>
|
1090
1183
|
# option is true callbacks in the join models are triggered except destroy callbacks, since deletion is
|
1091
|
-
# direct.
|
1184
|
+
# direct by default. You can specify <tt>dependent: :destroy</tt> or
|
1185
|
+
# <tt>dependent: :nullify</tt> to override this.
|
1092
1186
|
# [collection_singular_ids]
|
1093
1187
|
# Returns an array of the associated objects' ids
|
1094
1188
|
# [collection_singular_ids=ids]
|
@@ -1105,10 +1199,10 @@ module ActiveRecord
|
|
1105
1199
|
# [collection.size]
|
1106
1200
|
# Returns the number of associated objects.
|
1107
1201
|
# [collection.find(...)]
|
1108
|
-
# Finds an associated object according to the same rules as
|
1202
|
+
# Finds an associated object according to the same rules as ActiveRecord::FinderMethods#find.
|
1109
1203
|
# [collection.exists?(...)]
|
1110
1204
|
# Checks whether an associated object with the given conditions exists.
|
1111
|
-
# Uses the same rules as
|
1205
|
+
# Uses the same rules as ActiveRecord::FinderMethods#exists?.
|
1112
1206
|
# [collection.build(attributes = {}, ...)]
|
1113
1207
|
# Returns one or more new objects of the collection type that have been instantiated
|
1114
1208
|
# with +attributes+ and linked to this object through a foreign key, but have not yet
|
@@ -1119,7 +1213,7 @@ module ActiveRecord
|
|
1119
1213
|
# been saved (if it passed the validation). *Note*: This only works if the base model
|
1120
1214
|
# already exists in the DB, not if it is a new (unsaved) record!
|
1121
1215
|
# [collection.create!(attributes = {})]
|
1122
|
-
# Does the same as <tt>collection.create</tt>, but raises
|
1216
|
+
# Does the same as <tt>collection.create</tt>, but raises ActiveRecord::RecordInvalid
|
1123
1217
|
# if the record is invalid.
|
1124
1218
|
#
|
1125
1219
|
# === Example
|
@@ -1171,11 +1265,11 @@ module ActiveRecord
|
|
1171
1265
|
# [:class_name]
|
1172
1266
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
1173
1267
|
# 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
|
1268
|
+
# to the +Product+ class, but if the real class name is +SpecialProduct+, you'll have to
|
1175
1269
|
# specify it with this option.
|
1176
1270
|
# [:foreign_key]
|
1177
1271
|
# 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
|
1272
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_many
|
1179
1273
|
# association will use "person_id" as the default <tt>:foreign_key</tt>.
|
1180
1274
|
# [:foreign_type]
|
1181
1275
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
@@ -1199,20 +1293,20 @@ module ActiveRecord
|
|
1199
1293
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
|
1200
1294
|
#
|
1201
1295
|
# If using with the <tt>:through</tt> option, the association on the join model must be
|
1202
|
-
# a
|
1296
|
+
# a #belongs_to, and the records which get deleted are the join records, rather than
|
1203
1297
|
# the associated records.
|
1204
1298
|
# [:counter_cache]
|
1205
1299
|
# 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
|
1300
|
+
# when you customized the name of your <tt>:counter_cache</tt> on the #belongs_to association.
|
1207
1301
|
# [:as]
|
1208
|
-
# Specifies a polymorphic interface (See
|
1302
|
+
# Specifies a polymorphic interface (See #belongs_to).
|
1209
1303
|
# [:through]
|
1210
1304
|
# Specifies an association through which to perform the query. This can be any other type
|
1211
1305
|
# of association, including other <tt>:through</tt> associations. Options for <tt>:class_name</tt>,
|
1212
1306
|
# <tt>:primary_key</tt> and <tt>:foreign_key</tt> are ignored, as the association uses the
|
1213
1307
|
# source reflection.
|
1214
1308
|
#
|
1215
|
-
# If the association on the join model is a
|
1309
|
+
# If the association on the join model is a #belongs_to, the collection can be modified
|
1216
1310
|
# and the records on the <tt>:through</tt> model will be automatically created and removed
|
1217
1311
|
# as appropriate. Otherwise, the collection is read-only, so you should manipulate the
|
1218
1312
|
# <tt>:through</tt> association directly.
|
@@ -1223,13 +1317,13 @@ module ActiveRecord
|
|
1223
1317
|
# the appropriate join model records when they are saved. (See the 'Association Join Models'
|
1224
1318
|
# section above.)
|
1225
1319
|
# [:source]
|
1226
|
-
# Specifies the source association name used by <tt
|
1320
|
+
# Specifies the source association name used by #has_many <tt>:through</tt> queries.
|
1227
1321
|
# Only use it if the name cannot be inferred from the association.
|
1228
1322
|
# <tt>has_many :subscribers, through: :subscriptions</tt> will look for either <tt>:subscribers</tt> or
|
1229
1323
|
# <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
|
1230
1324
|
# [:source_type]
|
1231
|
-
# Specifies type of the source association used by <tt
|
1232
|
-
# association is a polymorphic
|
1325
|
+
# Specifies type of the source association used by #has_many <tt>:through</tt> queries where the source
|
1326
|
+
# association is a polymorphic #belongs_to.
|
1233
1327
|
# [:validate]
|
1234
1328
|
# If +false+, don't validate the associated objects when saving the parent object. true by default.
|
1235
1329
|
# [:autosave]
|
@@ -1239,18 +1333,23 @@ module ActiveRecord
|
|
1239
1333
|
# +before_save+ callback. Because callbacks are run in the order they are defined, associated objects
|
1240
1334
|
# may need to be explicitly saved in any user-defined +before_save+ callbacks.
|
1241
1335
|
#
|
1242
|
-
# Note that
|
1336
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1337
|
+
# <tt>:autosave</tt> to <tt>true</tt>.
|
1243
1338
|
# [:inverse_of]
|
1244
|
-
# Specifies the name of the
|
1245
|
-
# that is the inverse of this
|
1339
|
+
# Specifies the name of the #belongs_to association on the associated object
|
1340
|
+
# that is the inverse of this #has_many association. Does not work in combination
|
1246
1341
|
# with <tt>:through</tt> or <tt>:as</tt> options.
|
1247
1342
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1343
|
+
# [:extend]
|
1344
|
+
# Specifies a module or array of modules that will be extended into the association object returned.
|
1345
|
+
# Useful for defining methods on associations, especially when they should be shared between multiple
|
1346
|
+
# association objects.
|
1248
1347
|
#
|
1249
1348
|
# Option examples:
|
1250
|
-
# has_many :comments, -> { order
|
1251
|
-
# has_many :comments, -> { includes
|
1349
|
+
# has_many :comments, -> { order("posted_on") }
|
1350
|
+
# has_many :comments, -> { includes(:author) }
|
1252
1351
|
# has_many :people, -> { where(deleted: false).order("name") }, class_name: "Person"
|
1253
|
-
# has_many :tracks, -> { order
|
1352
|
+
# has_many :tracks, -> { order("position") }, dependent: :destroy
|
1254
1353
|
# has_many :comments, dependent: :nullify
|
1255
1354
|
# has_many :tags, as: :taggable
|
1256
1355
|
# has_many :reports, -> { readonly }
|
@@ -1262,8 +1361,8 @@ module ActiveRecord
|
|
1262
1361
|
|
1263
1362
|
# Specifies a one-to-one association with another class. This method should only be used
|
1264
1363
|
# 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
|
1364
|
+
# then you should use #belongs_to instead. See also ActiveRecord::Associations::ClassMethods's overview
|
1365
|
+
# on when to use #has_one and when to use #belongs_to.
|
1267
1366
|
#
|
1268
1367
|
# The following methods for retrieval and query of a single associated object will be added:
|
1269
1368
|
#
|
@@ -1285,7 +1384,7 @@ module ActiveRecord
|
|
1285
1384
|
# with +attributes+, linked to this object through a foreign key, and that
|
1286
1385
|
# has already been saved (if it passed the validation).
|
1287
1386
|
# [create_association!(attributes = {})]
|
1288
|
-
# Does the same as <tt>create_association</tt>, but raises
|
1387
|
+
# Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
|
1289
1388
|
# if the record is invalid.
|
1290
1389
|
#
|
1291
1390
|
# === Example
|
@@ -1326,9 +1425,11 @@ module ActiveRecord
|
|
1326
1425
|
# * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Callbacks are not executed.
|
1327
1426
|
# * <tt>:restrict_with_exception</tt> causes an exception to be raised if there is an associated record
|
1328
1427
|
# * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
|
1428
|
+
#
|
1429
|
+
# Note that <tt>:dependent</tt> option is ignored when using <tt>:through</tt> option.
|
1329
1430
|
# [:foreign_key]
|
1330
1431
|
# 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
|
1432
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_one association
|
1332
1433
|
# will use "person_id" as the default <tt>:foreign_key</tt>.
|
1333
1434
|
# [:foreign_type]
|
1334
1435
|
# Specify the column used to store the associated object's type, if this is a polymorphic
|
@@ -1339,20 +1440,20 @@ module ActiveRecord
|
|
1339
1440
|
# [:primary_key]
|
1340
1441
|
# Specify the method that returns the primary key used for the association. By default this is +id+.
|
1341
1442
|
# [:as]
|
1342
|
-
# Specifies a polymorphic interface (See
|
1443
|
+
# Specifies a polymorphic interface (See #belongs_to).
|
1343
1444
|
# [:through]
|
1344
1445
|
# Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>,
|
1345
1446
|
# <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
|
1447
|
+
# source reflection. You can only use a <tt>:through</tt> query through a #has_one
|
1448
|
+
# or #belongs_to association on the join model.
|
1348
1449
|
# [:source]
|
1349
|
-
# Specifies the source association name used by <tt
|
1450
|
+
# Specifies the source association name used by #has_one <tt>:through</tt> queries.
|
1350
1451
|
# Only use it if the name cannot be inferred from the association.
|
1351
1452
|
# <tt>has_one :favorite, through: :favorites</tt> will look for a
|
1352
1453
|
# <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
|
1353
1454
|
# [:source_type]
|
1354
|
-
# Specifies type of the source association used by <tt
|
1355
|
-
# association is a polymorphic
|
1455
|
+
# Specifies type of the source association used by #has_one <tt>:through</tt> queries where the source
|
1456
|
+
# association is a polymorphic #belongs_to.
|
1356
1457
|
# [:validate]
|
1357
1458
|
# If +false+, don't validate the associated object when saving the parent object. +false+ by default.
|
1358
1459
|
# [:autosave]
|
@@ -1360,10 +1461,11 @@ module ActiveRecord
|
|
1360
1461
|
# when saving the parent object. If false, never save or destroy the associated object.
|
1361
1462
|
# By default, only save the associated object if it's a new record.
|
1362
1463
|
#
|
1363
|
-
# Note that
|
1464
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1465
|
+
# <tt>:autosave</tt> to <tt>true</tt>.
|
1364
1466
|
# [:inverse_of]
|
1365
|
-
# Specifies the name of the
|
1366
|
-
# that is the inverse of this
|
1467
|
+
# Specifies the name of the #belongs_to association on the associated object
|
1468
|
+
# that is the inverse of this #has_one association. Does not work in combination
|
1367
1469
|
# with <tt>:through</tt> or <tt>:as</tt> options.
|
1368
1470
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1369
1471
|
# [:required]
|
@@ -1375,12 +1477,12 @@ module ActiveRecord
|
|
1375
1477
|
# has_one :credit_card, dependent: :destroy # destroys the associated credit card
|
1376
1478
|
# has_one :credit_card, dependent: :nullify # updates the associated records foreign
|
1377
1479
|
# # key value to NULL rather than destroying it
|
1378
|
-
# has_one :last_comment, -> { order
|
1379
|
-
# has_one :project_manager, -> { where
|
1480
|
+
# has_one :last_comment, -> { order('posted_on') }, class_name: "Comment"
|
1481
|
+
# has_one :project_manager, -> { where(role: 'project_manager') }, class_name: "Person"
|
1380
1482
|
# has_one :attachment, as: :attachable
|
1381
1483
|
# has_one :boss, -> { readonly }
|
1382
1484
|
# has_one :club, through: :membership
|
1383
|
-
# has_one :primary_address, -> { where
|
1485
|
+
# has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
|
1384
1486
|
# has_one :credit_card, required: true
|
1385
1487
|
def has_one(name, scope = nil, options = {})
|
1386
1488
|
reflection = Builder::HasOne.build(self, name, scope, options)
|
@@ -1389,8 +1491,8 @@ module ActiveRecord
|
|
1389
1491
|
|
1390
1492
|
# Specifies a one-to-one association with another class. This method should only be used
|
1391
1493
|
# 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
|
1494
|
+
# then you should use #has_one instead. See also ActiveRecord::Associations::ClassMethods's overview
|
1495
|
+
# on when to use #has_one and when to use #belongs_to.
|
1394
1496
|
#
|
1395
1497
|
# Methods will be added for retrieval and query for a single associated object, for which
|
1396
1498
|
# this object holds an id:
|
@@ -1410,7 +1512,7 @@ module ActiveRecord
|
|
1410
1512
|
# with +attributes+, linked to this object through a foreign key, and that
|
1411
1513
|
# has already been saved (if it passed the validation).
|
1412
1514
|
# [create_association!(attributes = {})]
|
1413
|
-
# Does the same as <tt>create_association</tt>, but raises
|
1515
|
+
# Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
|
1414
1516
|
# if the record is invalid.
|
1415
1517
|
#
|
1416
1518
|
# === Example
|
@@ -1430,7 +1532,7 @@ module ActiveRecord
|
|
1430
1532
|
# when you access the associated object.
|
1431
1533
|
#
|
1432
1534
|
# Scope examples:
|
1433
|
-
# belongs_to :
|
1535
|
+
# belongs_to :firm, -> { where(id: 2) }
|
1434
1536
|
# belongs_to :user, -> { joins(:friends) }
|
1435
1537
|
# belongs_to :level, ->(level) { where("game_level > ?", level.current) }
|
1436
1538
|
#
|
@@ -1457,12 +1559,12 @@ module ActiveRecord
|
|
1457
1559
|
# [:dependent]
|
1458
1560
|
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
|
1459
1561
|
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
|
1460
|
-
# This option should not be specified when
|
1461
|
-
# a
|
1562
|
+
# This option should not be specified when #belongs_to is used in conjunction with
|
1563
|
+
# a #has_many relationship on another class because of the potential to leave
|
1462
1564
|
# orphaned records behind.
|
1463
1565
|
# [:counter_cache]
|
1464
|
-
# Caches the number of belonging objects on the associate class through the use of
|
1465
|
-
# and
|
1566
|
+
# Caches the number of belonging objects on the associate class through the use of CounterCache::ClassMethods#increment_counter
|
1567
|
+
# and CounterCache::ClassMethods#decrement_counter. The counter cache is incremented when an object of this
|
1466
1568
|
# class is created and decremented when it's destroyed. This requires that a column
|
1467
1569
|
# named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
|
1468
1570
|
# is used on the associate class (such as a Post class) - that is the migration for
|
@@ -1484,20 +1586,25 @@ module ActiveRecord
|
|
1484
1586
|
# If false, never save or destroy the associated object.
|
1485
1587
|
# By default, only save the associated object if it's a new record.
|
1486
1588
|
#
|
1487
|
-
# Note that
|
1589
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for
|
1590
|
+
# sets <tt>:autosave</tt> to <tt>true</tt>.
|
1488
1591
|
# [:touch]
|
1489
1592
|
# If true, the associated object will be touched (the updated_at/on attributes set to current time)
|
1490
1593
|
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
1491
1594
|
# will be updated with the current time in addition to the updated_at/on attribute.
|
1492
1595
|
# [:inverse_of]
|
1493
|
-
# Specifies the name of the
|
1494
|
-
# object that is the inverse of this
|
1596
|
+
# Specifies the name of the #has_one or #has_many association on the associated
|
1597
|
+
# object that is the inverse of this #belongs_to association. Does not work in
|
1495
1598
|
# combination with the <tt>:polymorphic</tt> options.
|
1496
1599
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1600
|
+
# [:optional]
|
1601
|
+
# When set to +true+, the association will not have its presence validated.
|
1497
1602
|
# [:required]
|
1498
1603
|
# When set to +true+, the association will also have its presence validated.
|
1499
1604
|
# This will validate the association itself, not the id. You can use
|
1500
1605
|
# +:inverse_of+ to avoid an extra query during validation.
|
1606
|
+
# NOTE: <tt>required</tt> is set to <tt>true</tt> by default and is deprecated. If
|
1607
|
+
# you don't want to have association presence validated, use <tt>optional: true</tt>.
|
1501
1608
|
#
|
1502
1609
|
# Option examples:
|
1503
1610
|
# belongs_to :firm, foreign_key: "client_of"
|
@@ -1508,9 +1615,9 @@ module ActiveRecord
|
|
1508
1615
|
# belongs_to :attachable, polymorphic: true
|
1509
1616
|
# belongs_to :project, -> { readonly }
|
1510
1617
|
# belongs_to :post, counter_cache: true
|
1511
|
-
# belongs_to :
|
1618
|
+
# belongs_to :comment, touch: true
|
1512
1619
|
# belongs_to :company, touch: :employees_last_updated_at
|
1513
|
-
# belongs_to :
|
1620
|
+
# belongs_to :user, optional: true
|
1514
1621
|
def belongs_to(name, scope = nil, options = {})
|
1515
1622
|
reflection = Builder::BelongsTo.build(self, name, scope, options)
|
1516
1623
|
Reflection.add_reflection self, name, reflection
|
@@ -1533,12 +1640,9 @@ module ActiveRecord
|
|
1533
1640
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
1534
1641
|
# join table with a migration such as this:
|
1535
1642
|
#
|
1536
|
-
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration
|
1643
|
+
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[5.0]
|
1537
1644
|
# def change
|
1538
|
-
#
|
1539
|
-
# t.integer :developer_id
|
1540
|
-
# t.integer :project_id
|
1541
|
-
# end
|
1645
|
+
# create_join_table :developers, :projects
|
1542
1646
|
# end
|
1543
1647
|
# end
|
1544
1648
|
#
|
@@ -1580,10 +1684,10 @@ module ActiveRecord
|
|
1580
1684
|
# [collection.find(id)]
|
1581
1685
|
# Finds an associated object responding to the +id+ and that
|
1582
1686
|
# meets the condition that it has to be associated with this object.
|
1583
|
-
# Uses the same rules as
|
1687
|
+
# Uses the same rules as ActiveRecord::FinderMethods#find.
|
1584
1688
|
# [collection.exists?(...)]
|
1585
1689
|
# Checks whether an associated object with the given conditions exists.
|
1586
|
-
# Uses the same rules as
|
1690
|
+
# Uses the same rules as ActiveRecord::FinderMethods#exists?.
|
1587
1691
|
# [collection.build(attributes = {})]
|
1588
1692
|
# Returns a new object of the collection type that has been instantiated
|
1589
1693
|
# with +attributes+ and linked to this object through the join table, but has not yet been saved.
|
@@ -1618,7 +1722,7 @@ module ActiveRecord
|
|
1618
1722
|
# query when you access the associated collection.
|
1619
1723
|
#
|
1620
1724
|
# Scope examples:
|
1621
|
-
# has_and_belongs_to_many :projects, -> { includes
|
1725
|
+
# has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
|
1622
1726
|
# has_and_belongs_to_many :categories, ->(category) {
|
1623
1727
|
# where("default_category = ?", category.name)
|
1624
1728
|
# }
|
@@ -1647,19 +1751,17 @@ module ActiveRecord
|
|
1647
1751
|
# [:join_table]
|
1648
1752
|
# Specify the name of the join table if the default based on lexical order isn't what you want.
|
1649
1753
|
# <b>WARNING:</b> If you're overwriting the table name of either class, the +table_name+ method
|
1650
|
-
# MUST be declared underneath any
|
1754
|
+
# MUST be declared underneath any #has_and_belongs_to_many declaration in order to work.
|
1651
1755
|
# [:foreign_key]
|
1652
1756
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1653
1757
|
# of this class in lower-case and "_id" suffixed. So a Person class that makes
|
1654
|
-
# a
|
1758
|
+
# a #has_and_belongs_to_many association to Project will use "person_id" as the
|
1655
1759
|
# default <tt>:foreign_key</tt>.
|
1656
1760
|
# [:association_foreign_key]
|
1657
1761
|
# Specify the foreign key used for the association on the receiving side of the association.
|
1658
1762
|
# 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
|
1763
|
+
# So if a Person class makes a #has_and_belongs_to_many association to Project,
|
1660
1764
|
# 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
1765
|
# [:validate]
|
1664
1766
|
# If +false+, don't validate the associated objects when saving the parent object. +true+ by default.
|
1665
1767
|
# [:autosave]
|
@@ -1668,11 +1770,12 @@ module ActiveRecord
|
|
1668
1770
|
# If false, never save or destroy the associated objects.
|
1669
1771
|
# By default, only save associated objects that are new records.
|
1670
1772
|
#
|
1671
|
-
# Note that
|
1773
|
+
# Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
|
1774
|
+
# <tt>:autosave</tt> to <tt>true</tt>.
|
1672
1775
|
#
|
1673
1776
|
# Option examples:
|
1674
1777
|
# has_and_belongs_to_many :projects
|
1675
|
-
# has_and_belongs_to_many :projects, -> { includes
|
1778
|
+
# has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
|
1676
1779
|
# has_and_belongs_to_many :nations, class_name: "Country"
|
1677
1780
|
# has_and_belongs_to_many :categories, join_table: "prods_cats"
|
1678
1781
|
# has_and_belongs_to_many :categories, -> { readonly }
|
@@ -1688,16 +1791,14 @@ module ActiveRecord
|
|
1688
1791
|
|
1689
1792
|
join_model = builder.through_model
|
1690
1793
|
|
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
1794
|
const_set join_model.name, join_model
|
1795
|
+
private_constant join_model.name
|
1695
1796
|
|
1696
1797
|
middle_reflection = builder.middle_reflection join_model
|
1697
1798
|
|
1698
1799
|
Builder::HasMany.define_callbacks self, middle_reflection
|
1699
1800
|
Reflection.add_reflection self, middle_reflection.name, middle_reflection
|
1700
|
-
middle_reflection.parent_reflection =
|
1801
|
+
middle_reflection.parent_reflection = habtm_reflection
|
1701
1802
|
|
1702
1803
|
include Module.new {
|
1703
1804
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
@@ -1718,7 +1819,7 @@ module ActiveRecord
|
|
1718
1819
|
end
|
1719
1820
|
|
1720
1821
|
has_many name, scope, hm_options, &extension
|
1721
|
-
self._reflections[name.to_s].parent_reflection =
|
1822
|
+
self._reflections[name.to_s].parent_reflection = habtm_reflection
|
1722
1823
|
end
|
1723
1824
|
end
|
1724
1825
|
end
|