activerecord 3.0.0.rc → 3.0.0.rc2
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.
- data/CHANGELOG +6 -1
- data/README.rdoc +9 -9
- data/lib/active_record/aggregations.rb +64 -51
- data/lib/active_record/association_preload.rb +11 -9
- data/lib/active_record/associations.rb +300 -204
- data/lib/active_record/associations/association_collection.rb +7 -2
- data/lib/active_record/associations/belongs_to_association.rb +9 -5
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +7 -6
- data/lib/active_record/associations/has_many_association.rb +6 -6
- data/lib/active_record/associations/has_many_through_association.rb +4 -3
- data/lib/active_record/associations/has_one_association.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +2 -1
- data/lib/active_record/attribute_methods/write.rb +2 -2
- data/lib/active_record/autosave_association.rb +54 -72
- data/lib/active_record/base.rb +167 -108
- data/lib/active_record/callbacks.rb +43 -35
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +8 -11
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +0 -8
- data/lib/active_record/connection_adapters/abstract/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +8 -6
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +5 -3
- data/lib/active_record/connection_adapters/mysql_adapter.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +9 -5
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +5 -5
- data/lib/active_record/dynamic_finder_match.rb +3 -3
- data/lib/active_record/dynamic_scope_match.rb +1 -1
- data/lib/active_record/errors.rb +9 -5
- data/lib/active_record/fixtures.rb +36 -22
- data/lib/active_record/locale/en.yml +2 -2
- data/lib/active_record/migration.rb +36 -36
- data/lib/active_record/named_scope.rb +23 -11
- data/lib/active_record/nested_attributes.rb +3 -3
- data/lib/active_record/observer.rb +3 -3
- data/lib/active_record/persistence.rb +44 -29
- data/lib/active_record/railtie.rb +5 -8
- data/lib/active_record/railties/databases.rake +1 -1
- data/lib/active_record/reflection.rb +52 -52
- data/lib/active_record/relation.rb +26 -19
- data/lib/active_record/relation/batches.rb +4 -4
- data/lib/active_record/relation/calculations.rb +58 -34
- data/lib/active_record/relation/finder_methods.rb +21 -12
- data/lib/active_record/relation/query_methods.rb +26 -31
- data/lib/active_record/relation/spawn_methods.rb +17 -5
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +12 -12
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/serializers/xml_serializer.rb +1 -1
- data/lib/active_record/session_store.rb +9 -9
- data/lib/active_record/test_case.rb +2 -2
- data/lib/active_record/timestamp.rb +31 -32
- data/lib/active_record/validations/associated.rb +4 -3
- data/lib/active_record/validations/uniqueness.rb +15 -11
- data/lib/active_record/version.rb +1 -1
- metadata +17 -16
data/CHANGELOG
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
*Rails 3.0.0 [release candidate 2] (August 23rd, 2010)*
|
2
|
+
|
3
|
+
* No material changes (see http://github.com/rails/rails/compare/v3.0.0_RC...v3.0.0_RC2 for gory details)
|
4
|
+
|
5
|
+
|
1
6
|
*Rails 3.0.0 [release candidate] (July 26th, 2010)*
|
2
7
|
|
3
8
|
* Changed update_attribute to not run callbacks and update the record directly in the database [Neeraj Singh]
|
@@ -966,7 +971,7 @@ during calendar reform. #7649, #7724 [fedot, Geoff Buesing]
|
|
966
971
|
* Made increment_counter/decrement_counter play nicely with optimistic locking, and added a more general update_counters method [Jamis Buck]
|
967
972
|
|
968
973
|
* Reworked David's query cache to be available as Model.cache {...}. For the duration of the block no select query should be run more then once. Any inserts/deletes/executes will flush the whole cache however [Tobias Lütke]
|
969
|
-
Task.cache { Task.find(1); Task.find(1) }
|
974
|
+
Task.cache { Task.find(1); Task.find(1) } # => 1 query
|
970
975
|
|
971
976
|
* When dealing with SQLite3, use the table_info pragma helper, so that the bindings can do some translation for when sqlite3 breaks incompatibly between point releases. [Jamis Buck]
|
972
977
|
|
data/README.rdoc
CHANGED
@@ -19,19 +19,19 @@ A short rundown of some of the major features:
|
|
19
19
|
|
20
20
|
class Product < ActiveRecord::Base
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
The Product class is automatically mapped to the table named "products",
|
24
24
|
which might look like this:
|
25
|
-
|
25
|
+
|
26
26
|
CREATE TABLE products (
|
27
27
|
id int(11) NOT NULL auto_increment,
|
28
28
|
name varchar(255),
|
29
29
|
PRIMARY KEY (id)
|
30
30
|
);
|
31
|
-
|
31
|
+
|
32
32
|
This would also define the following accessors: `Product#name` and
|
33
33
|
`Product#name=(new_name)`
|
34
|
-
|
34
|
+
|
35
35
|
{Learn more}[link:classes/ActiveRecord/Base.html]
|
36
36
|
|
37
37
|
|
@@ -51,7 +51,7 @@ A short rundown of some of the major features:
|
|
51
51
|
class Account < ActiveRecord::Base
|
52
52
|
composed_of :balance, :class_name => "Money",
|
53
53
|
:mapping => %w(balance amount)
|
54
|
-
composed_of :address,
|
54
|
+
composed_of :address,
|
55
55
|
:mapping => [%w(address_street street), %w(address_city city)]
|
56
56
|
end
|
57
57
|
|
@@ -91,7 +91,7 @@ A short rundown of some of the major features:
|
|
91
91
|
{Learn more}[link:classes/ActiveRecord/Observer.html]
|
92
92
|
|
93
93
|
|
94
|
-
* Inheritance hierarchies
|
94
|
+
* Inheritance hierarchies
|
95
95
|
|
96
96
|
class Company < ActiveRecord::Base; end
|
97
97
|
class Firm < Company; end
|
@@ -170,7 +170,7 @@ A short rundown of some of the major features:
|
|
170
170
|
{Learn more}[link:classes/ActiveRecord/Migration.html]
|
171
171
|
|
172
172
|
|
173
|
-
== Philosophy
|
173
|
+
== Philosophy
|
174
174
|
|
175
175
|
Active Record is an implementation of the object-relational mapping (ORM)
|
176
176
|
pattern[http://www.martinfowler.com/eaaCatalog/activeRecord.html] by the same
|
@@ -179,7 +179,7 @@ name described by Martin Fowler:
|
|
179
179
|
"An object that wraps a row in a database table or view,
|
180
180
|
encapsulates the database access, and adds domain logic on that data."
|
181
181
|
|
182
|
-
Active Record attempts to provide a coherent wrapper as a solution for the inconvenience that is
|
182
|
+
Active Record attempts to provide a coherent wrapper as a solution for the inconvenience that is
|
183
183
|
object-relational mapping. The prime directive for this mapping has been to minimize
|
184
184
|
the amount of code needed to build a real-world domain model. This is made possible
|
185
185
|
by relying on a number of conventions that make it easy for Active Record to infer
|
@@ -188,7 +188,7 @@ complex relations and structures from a minimal amount of explicit direction.
|
|
188
188
|
Convention over Configuration:
|
189
189
|
* No XML-files!
|
190
190
|
* Lots of reflection and run-time extension
|
191
|
-
* Magic is not inherently a bad word
|
191
|
+
* Magic is not inherently a bad word
|
192
192
|
|
193
193
|
Admit the Database:
|
194
194
|
* Lets you drop down to SQL for odd cases and performance
|
@@ -9,11 +9,13 @@ module ActiveRecord
|
|
9
9
|
end unless self.new_record?
|
10
10
|
end
|
11
11
|
|
12
|
-
# Active Record implements aggregation through a macro-like class method called +composed_of+
|
13
|
-
# as value objects. It expresses relationships like "Account [is]
|
14
|
-
# composed of [
|
15
|
-
#
|
16
|
-
#
|
12
|
+
# Active Record implements aggregation through a macro-like class method called +composed_of+
|
13
|
+
# for representing attributes as value objects. It expresses relationships like "Account [is]
|
14
|
+
# composed of Money [among other things]" or "Person [is] composed of [an] address". Each call
|
15
|
+
# to the macro adds a description of how the value objects are created from the attributes of
|
16
|
+
# the entity object (when the entity is initialized either as a new object or from finding an
|
17
|
+
# existing object) and how it can be turned back into attributes (when the entity is saved to
|
18
|
+
# the database).
|
17
19
|
#
|
18
20
|
# class Customer < ActiveRecord::Base
|
19
21
|
# composed_of :balance, :class_name => "Money", :mapping => %w(balance amount)
|
@@ -68,9 +70,10 @@ module ActiveRecord
|
|
68
70
|
# end
|
69
71
|
# end
|
70
72
|
#
|
71
|
-
# Now it's possible to access attributes from the database through the value objects instead. If
|
72
|
-
# composition the same as the attribute's name, it will be the only way to
|
73
|
-
# +balance+ attribute. You interact with the value
|
73
|
+
# Now it's possible to access attributes from the database through the value objects instead. If
|
74
|
+
# you choose to name the composition the same as the attribute's name, it will be the only way to
|
75
|
+
# access that attribute. That's the case with our +balance+ attribute. You interact with the value
|
76
|
+
# objects just like you would any other attribute, though:
|
74
77
|
#
|
75
78
|
# customer.balance = Money.new(20) # sets the Money value object and the attribute
|
76
79
|
# customer.balance # => Money value object
|
@@ -79,8 +82,8 @@ module ActiveRecord
|
|
79
82
|
# customer.balance == Money.new(20) # => true
|
80
83
|
# customer.balance < Money.new(5) # => false
|
81
84
|
#
|
82
|
-
# Value objects can also be composed of multiple attributes, such as the case of Address. The order
|
83
|
-
# determine the order of the parameters.
|
85
|
+
# Value objects can also be composed of multiple attributes, such as the case of Address. The order
|
86
|
+
# of the mappings will determine the order of the parameters.
|
84
87
|
#
|
85
88
|
# customer.address_street = "Hyancintvej"
|
86
89
|
# customer.address_city = "Copenhagen"
|
@@ -91,38 +94,43 @@ module ActiveRecord
|
|
91
94
|
#
|
92
95
|
# == Writing value objects
|
93
96
|
#
|
94
|
-
# Value objects are immutable and interchangeable objects that represent a given value, such as
|
95
|
-
# $5. Two Money objects both representing $5 should be equal (through
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
97
|
+
# Value objects are immutable and interchangeable objects that represent a given value, such as
|
98
|
+
# a Money object representing $5. Two Money objects both representing $5 should be equal (through
|
99
|
+
# methods such as <tt>==</tt> and <tt><=></tt> from Comparable if ranking makes sense). This is
|
100
|
+
# unlike entity objects where equality is determined by identity. An entity class such as Customer can
|
101
|
+
# easily have two different objects that both have an address on Hyancintvej. Entity identity is
|
102
|
+
# determined by object or relational unique identifiers (such as primary keys). Normal
|
103
|
+
# ActiveRecord::Base classes are entity objects.
|
99
104
|
#
|
100
|
-
# It's also important to treat the value objects as immutable. Don't allow the Money object to have
|
101
|
-
# creation. Create a new Money object with the new value instead. This
|
102
|
-
# returns a new value object instead of changing
|
103
|
-
#
|
105
|
+
# It's also important to treat the value objects as immutable. Don't allow the Money object to have
|
106
|
+
# its amount changed after creation. Create a new Money object with the new value instead. This
|
107
|
+
# is exemplified by the Money#exchange_to method that returns a new value object instead of changing
|
108
|
+
# its own values. Active Record won't persist value objects that have been changed through means
|
109
|
+
# other than the writer method.
|
104
110
|
#
|
105
|
-
# The immutable requirement is enforced by Active Record by freezing any object assigned as a value
|
106
|
-
# change it afterwards will result in a ActiveSupport::FrozenObjectError.
|
111
|
+
# The immutable requirement is enforced by Active Record by freezing any object assigned as a value
|
112
|
+
# object. Attempting to change it afterwards will result in a ActiveSupport::FrozenObjectError.
|
107
113
|
#
|
108
|
-
# Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not
|
109
|
-
# immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable
|
114
|
+
# Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not
|
115
|
+
# keeping value objects immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable
|
110
116
|
#
|
111
117
|
# == Custom constructors and converters
|
112
118
|
#
|
113
|
-
# By default value objects are initialized by calling the <tt>new</tt> constructor of the value
|
114
|
-
# mapped attributes, in the order specified by the <tt>:mapping</tt>
|
115
|
-
# this convention then +composed_of+ allows
|
119
|
+
# By default value objects are initialized by calling the <tt>new</tt> constructor of the value
|
120
|
+
# class passing each of the mapped attributes, in the order specified by the <tt>:mapping</tt>
|
121
|
+
# option, as arguments. If the value class doesn't support this convention then +composed_of+ allows
|
122
|
+
# a custom constructor to be specified.
|
116
123
|
#
|
117
|
-
# When a new value is assigned to the value object the default assumption is that the new value
|
118
|
-
# class. Specifying a custom converter allows the new value to be automatically
|
119
|
-
# necessary.
|
124
|
+
# When a new value is assigned to the value object the default assumption is that the new value
|
125
|
+
# is an instance of the value class. Specifying a custom converter allows the new value to be automatically
|
126
|
+
# converted to an instance of value class if necessary.
|
120
127
|
#
|
121
|
-
# For example, the NetworkResource model has +network_address+ and +cidr_range+ attributes that
|
122
|
-
# NetAddr::CIDR value class (http://netaddr.rubyforge.org). The constructor
|
123
|
-
# expects a CIDR address string as a parameter. New
|
124
|
-
#
|
125
|
-
#
|
128
|
+
# For example, the NetworkResource model has +network_address+ and +cidr_range+ attributes that
|
129
|
+
# should be aggregated using the NetAddr::CIDR value class (http://netaddr.rubyforge.org). The constructor
|
130
|
+
# for the value class is called +create+ and it expects a CIDR address string as a parameter. New
|
131
|
+
# values can be assigned to the value object using either another NetAddr::CIDR object, a string
|
132
|
+
# or an array. The <tt>:constructor</tt> and <tt>:converter</tt> options can be used to meet
|
133
|
+
# these requirements:
|
126
134
|
#
|
127
135
|
# class NetworkResource < ActiveRecord::Base
|
128
136
|
# composed_of :cidr,
|
@@ -149,9 +157,9 @@ module ActiveRecord
|
|
149
157
|
#
|
150
158
|
# == Finding records by a value object
|
151
159
|
#
|
152
|
-
# Once a +composed_of+ relationship is specified for a model, records can be loaded from the database
|
153
|
-
# of the value object in the conditions hash. The following example
|
154
|
-
# +balance_currency+ equal to "USD":
|
160
|
+
# Once a +composed_of+ relationship is specified for a model, records can be loaded from the database
|
161
|
+
# by specifying an instance of the value object in the conditions hash. The following example
|
162
|
+
# finds all customers with +balance_amount+ equal to 20 and +balance_currency+ equal to "USD":
|
155
163
|
#
|
156
164
|
# Customer.find(:all, :conditions => {:balance => Money.new(20, "USD")})
|
157
165
|
#
|
@@ -160,23 +168,28 @@ module ActiveRecord
|
|
160
168
|
# <tt>composed_of :address</tt> adds <tt>address</tt> and <tt>address=(new_address)</tt> methods.
|
161
169
|
#
|
162
170
|
# Options are:
|
163
|
-
# * <tt>:class_name</tt> - Specifies the class name of the association. Use it only if that name
|
164
|
-
# from the part id. So <tt>composed_of :address</tt> will by default be linked
|
165
|
-
# if the real class name is CompanyAddress, you'll have to specify it
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
169
|
-
#
|
171
|
+
# * <tt>:class_name</tt> - Specifies the class name of the association. Use it only if that name
|
172
|
+
# can't be inferred from the part id. So <tt>composed_of :address</tt> will by default be linked
|
173
|
+
# to the Address class, but if the real class name is CompanyAddress, you'll have to specify it
|
174
|
+
# with this option.
|
175
|
+
# * <tt>:mapping</tt> - Specifies the mapping of entity attributes to attributes of the value
|
176
|
+
# object. Each mapping is represented as an array where the first item is the name of the
|
177
|
+
# entity attribute and the second item is the name the attribute in the value object. The
|
178
|
+
# order in which mappings are defined determine the order in which attributes are sent to the
|
179
|
+
# value class constructor.
|
170
180
|
# * <tt>:allow_nil</tt> - Specifies that the value object will not be instantiated when all mapped
|
171
|
-
# attributes are +nil+. Setting the value object to +nil+ has the effect of writing +nil+ to all
|
181
|
+
# attributes are +nil+. Setting the value object to +nil+ has the effect of writing +nil+ to all
|
182
|
+
# mapped attributes.
|
172
183
|
# This defaults to +false+.
|
173
|
-
# * <tt>:constructor</tt> - A symbol specifying the name of the constructor method or a Proc that
|
174
|
-
# initialize the value object. The constructor is passed all of the mapped attributes,
|
175
|
-
# are defined in the <tt>:mapping option</tt>, as arguments and uses them
|
184
|
+
# * <tt>:constructor</tt> - A symbol specifying the name of the constructor method or a Proc that
|
185
|
+
# is called to initialize the value object. The constructor is passed all of the mapped attributes,
|
186
|
+
# in the order that they are defined in the <tt>:mapping option</tt>, as arguments and uses them
|
187
|
+
# to instantiate a <tt>:class_name</tt> object.
|
176
188
|
# The default is <tt>:new</tt>.
|
177
|
-
# * <tt>:converter</tt> - A symbol specifying the name of a class method of <tt>:class_name</tt>
|
178
|
-
# called when a new value is assigned to the value object. The converter is
|
179
|
-
# in the assignment and is only called if the new value is
|
189
|
+
# * <tt>:converter</tt> - A symbol specifying the name of a class method of <tt>:class_name</tt>
|
190
|
+
# or a Proc that is called when a new value is assigned to the value object. The converter is
|
191
|
+
# passed the single value that is used in the assignment and is only called if the new value is
|
192
|
+
# not an instance of <tt>:class_name</tt>.
|
180
193
|
#
|
181
194
|
# Option examples:
|
182
195
|
# composed_of :temperature, :mapping => %w(reading celsius)
|
@@ -9,8 +9,8 @@ module ActiveRecord
|
|
9
9
|
# Implements the details of eager loading of Active Record associations.
|
10
10
|
# Application developers should not use this module directly.
|
11
11
|
#
|
12
|
-
# ActiveRecord::Base is extended with this module. The source code in
|
13
|
-
# ActiveRecord::Base references methods defined in this module.
|
12
|
+
# <tt>ActiveRecord::Base</tt> is extended with this module. The source code in
|
13
|
+
# <tt>ActiveRecord::Base</tt> references methods defined in this module.
|
14
14
|
#
|
15
15
|
# Note that 'eager loading' and 'preloading' are actually the same thing.
|
16
16
|
# However, there are two different eager loading strategies.
|
@@ -55,7 +55,7 @@ module ActiveRecord
|
|
55
55
|
# == Parameters
|
56
56
|
# +records+ is an array of ActiveRecord::Base. This array needs not be flat,
|
57
57
|
# i.e. +records+ itself may also contain arrays of records. In any case,
|
58
|
-
# +preload_associations+ will preload the associations
|
58
|
+
# +preload_associations+ will preload the all associations records by
|
59
59
|
# flattening +records+.
|
60
60
|
#
|
61
61
|
# +associations+ specifies one or more associations that you want to
|
@@ -110,8 +110,8 @@ module ActiveRecord
|
|
110
110
|
def preload_one_association(records, association, preload_options={})
|
111
111
|
class_to_reflection = {}
|
112
112
|
# Not all records have the same class, so group then preload
|
113
|
-
# group on the reflection itself so that if various subclass share the same association then
|
114
|
-
# unnecessarily
|
113
|
+
# group on the reflection itself so that if various subclass share the same association then
|
114
|
+
# we do not split them unnecessarily
|
115
115
|
records.group_by { |record| class_to_reflection[record.class] ||= record.class.reflections[association]}.each do |reflection, _records|
|
116
116
|
raise ConfigurationError, "Association named '#{ association }' was not found; perhaps you misspelled it?" unless reflection
|
117
117
|
|
@@ -149,7 +149,8 @@ module ActiveRecord
|
|
149
149
|
seen_keys = {}
|
150
150
|
associated_records.each do |associated_record|
|
151
151
|
#this is a has_one or belongs_to: there should only be one record.
|
152
|
-
#Unfortunately we can't (in portable way) ask the database for
|
152
|
+
#Unfortunately we can't (in portable way) ask the database for
|
153
|
+
#'all records where foo_id in (x,y,z), but please
|
153
154
|
# only one row per distinct foo_id' so this where we enforce that
|
154
155
|
next if seen_keys[associated_record[key].to_s]
|
155
156
|
seen_keys[associated_record[key].to_s] = true
|
@@ -162,7 +163,7 @@ module ActiveRecord
|
|
162
163
|
|
163
164
|
id_to_record_map.each do |id, records|
|
164
165
|
next if seen_keys.include?(id.to_s)
|
165
|
-
records.each {|record| record.send("set_#{reflection_name}_target", nil) }
|
166
|
+
records.each {|record| record.send("set_#{reflection_name}_target", nil) }
|
166
167
|
end
|
167
168
|
end
|
168
169
|
|
@@ -304,7 +305,8 @@ module ActiveRecord
|
|
304
305
|
polymorph_type = options[:foreign_type]
|
305
306
|
klasses_and_ids = {}
|
306
307
|
|
307
|
-
# Construct a mapping from klass to a list of ids to load and a mapping of those ids back
|
308
|
+
# Construct a mapping from klass to a list of ids to load and a mapping of those ids back
|
309
|
+
# to their parent_records
|
308
310
|
records.each do |record|
|
309
311
|
if klass = record.send(polymorph_type)
|
310
312
|
klass_id = record.send(primary_key_name)
|
@@ -370,7 +372,7 @@ module ActiveRecord
|
|
370
372
|
conditions << append_conditions(reflection, preload_options)
|
371
373
|
|
372
374
|
find_options = {
|
373
|
-
:select => preload_options[:select] || options[:select] || "#{table_name}.*",
|
375
|
+
:select => preload_options[:select] || options[:select] || Arel::SqlLiteral.new("#{table_name}.*"),
|
374
376
|
:include => preload_options[:include] || options[:include],
|
375
377
|
:conditions => [conditions, ids],
|
376
378
|
:joins => options[:joins],
|
@@ -35,7 +35,7 @@ module ActiveRecord
|
|
35
35
|
through_reflection = reflection.through_reflection
|
36
36
|
source_reflection_names = reflection.source_reflection_names
|
37
37
|
source_associations = reflection.through_reflection.klass.reflect_on_all_associations.collect { |a| a.name.inspect }
|
38
|
-
super("Could not find the source association(s) #{source_reflection_names.collect
|
38
|
+
super("Could not find the source association(s) #{source_reflection_names.collect{ |a| a.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)}?")
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -114,7 +114,7 @@ module ActiveRecord
|
|
114
114
|
autoload :HasOneAssociation, 'active_record/associations/has_one_association'
|
115
115
|
autoload :HasOneThroughAssociation, 'active_record/associations/has_one_through_association'
|
116
116
|
|
117
|
-
# Clears out the association cache
|
117
|
+
# Clears out the association cache.
|
118
118
|
def clear_association_cache #:nodoc:
|
119
119
|
self.class.reflect_on_all_associations.to_a.each do |assoc|
|
120
120
|
instance_variable_set "@#{assoc.name}", nil
|
@@ -122,7 +122,7 @@ module ActiveRecord
|
|
122
122
|
end
|
123
123
|
|
124
124
|
private
|
125
|
-
#
|
125
|
+
# Returns the specified association instance if it responds to :loaded?, nil otherwise.
|
126
126
|
def association_instance_get(name)
|
127
127
|
ivar = "@#{name}"
|
128
128
|
if instance_variable_defined?(ivar)
|
@@ -136,10 +136,12 @@ module ActiveRecord
|
|
136
136
|
instance_variable_set("@#{name}", association)
|
137
137
|
end
|
138
138
|
|
139
|
-
# Associations are a set of macro-like class methods for tying objects together through
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
139
|
+
# Associations are a set of macro-like class methods for tying objects together through
|
140
|
+
# foreign keys. They express relationships like "Project has one Project Manager"
|
141
|
+
# or "Project belongs to a Portfolio". Each macro adds a number of methods to the
|
142
|
+
# class which are specialized according to the collection or association symbol and the
|
143
|
+
# options hash. It works much the same way as Ruby's own <tt>attr*</tt>
|
144
|
+
# methods.
|
143
145
|
#
|
144
146
|
# class Project < ActiveRecord::Base
|
145
147
|
# belongs_to :portfolio
|
@@ -148,7 +150,8 @@ module ActiveRecord
|
|
148
150
|
# has_and_belongs_to_many :categories
|
149
151
|
# end
|
150
152
|
#
|
151
|
-
# The project class now has the following methods (and more) to ease the traversal and
|
153
|
+
# The project class now has the following methods (and more) to ease the traversal and
|
154
|
+
# manipulation of its relationships:
|
152
155
|
# * <tt>Project#portfolio, Project#portfolio=(portfolio), Project#portfolio.nil?</tt>
|
153
156
|
# * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt>
|
154
157
|
# * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone),</tt>
|
@@ -159,8 +162,9 @@ module ActiveRecord
|
|
159
162
|
#
|
160
163
|
# === A word of warning
|
161
164
|
#
|
162
|
-
# Don't create associations that have the same name as instance methods of
|
163
|
-
# adds a method with that name to
|
165
|
+
# Don't create associations that have the same name as instance methods of
|
166
|
+
# <tt>ActiveRecord::Base</tt>. Since the association adds a method with that name to
|
167
|
+
# its model, it will override the inherited method and break things.
|
164
168
|
# For instance, +attributes+ and +connection+ would be bad choices for association names.
|
165
169
|
#
|
166
170
|
# == Auto-generated methods
|
@@ -270,8 +274,8 @@ module ActiveRecord
|
|
270
274
|
#
|
271
275
|
# == Is it a +belongs_to+ or +has_one+ association?
|
272
276
|
#
|
273
|
-
# Both express a 1-1 relationship. The difference is mostly where to place the foreign
|
274
|
-
# declaring the +belongs_to+ relationship.
|
277
|
+
# Both express a 1-1 relationship. The difference is mostly where to place the foreign
|
278
|
+
# key, which goes on the table for the class declaring the +belongs_to+ relationship.
|
275
279
|
#
|
276
280
|
# class User < ActiveRecord::Base
|
277
281
|
# # I reference an account.
|
@@ -300,36 +304,45 @@ module ActiveRecord
|
|
300
304
|
#
|
301
305
|
# == Unsaved objects and associations
|
302
306
|
#
|
303
|
-
# You can manipulate objects and associations before they are saved to the database, but
|
304
|
-
# aware of, mostly involving the saving of
|
307
|
+
# You can manipulate objects and associations before they are saved to the database, but
|
308
|
+
# there is some special behavior you should be aware of, mostly involving the saving of
|
309
|
+
# associated objects.
|
305
310
|
#
|
306
|
-
#
|
311
|
+
# You can set the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>,
|
307
312
|
# <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association. Setting it
|
308
313
|
# to +true+ will _always_ save the members, whereas setting it to +false+ will
|
309
|
-
# _never_ save the members.
|
314
|
+
# _never_ save the members. More details about :autosave option is available at
|
315
|
+
# autosave_association.rb .
|
310
316
|
#
|
311
317
|
# === One-to-one associations
|
312
318
|
#
|
313
|
-
# * Assigning an object to a +has_one+ association automatically saves that object and
|
314
|
-
#
|
315
|
-
#
|
316
|
-
#
|
317
|
-
#
|
318
|
-
# *
|
319
|
-
#
|
319
|
+
# * Assigning an object to a +has_one+ association automatically saves that object and
|
320
|
+
# the object being replaced (if there is one), in order to update their primary
|
321
|
+
# keys - except if the parent object is unsaved (<tt>new_record? == true</tt>).
|
322
|
+
# * If either of these saves fail (due to one of the objects being invalid) the assignment
|
323
|
+
# statement returns +false+ and the assignment is cancelled.
|
324
|
+
# * If you wish to assign an object to a +has_one+ association without saving it,
|
325
|
+
# use the <tt>association.build</tt> method (documented below).
|
326
|
+
# * Assigning an object to a +belongs_to+ association does not save the object, since
|
327
|
+
# the foreign key field belongs on the parent. It does not save the parent either.
|
320
328
|
#
|
321
329
|
# === Collections
|
322
330
|
#
|
323
|
-
# * Adding an object to a collection (+has_many+ or +has_and_belongs_to_many+) automatically
|
324
|
-
#
|
325
|
-
#
|
326
|
-
# *
|
327
|
-
#
|
331
|
+
# * Adding an object to a collection (+has_many+ or +has_and_belongs_to_many+) automatically
|
332
|
+
# saves that object, except if the parent object (the owner of the collection) is not yet
|
333
|
+
# stored in the database.
|
334
|
+
# * If saving any of the objects being added to a collection (via <tt>push</tt> or similar)
|
335
|
+
# fails, then <tt>push</tt> returns +false+.
|
336
|
+
# * You can add an object to a collection without automatically saving it by using the
|
337
|
+
# <tt>collection.build</tt> method (documented below).
|
338
|
+
# * All unsaved (<tt>new_record? == true</tt>) members of the collection are automatically
|
339
|
+
# saved when the parent is saved.
|
328
340
|
#
|
329
341
|
# === Association callbacks
|
330
342
|
#
|
331
|
-
# Similar to the normal callbacks that hook into the lifecycle of an Active Record object,
|
332
|
-
# triggered when you add an object to or remove an
|
343
|
+
# Similar to the normal callbacks that hook into the lifecycle of an Active Record object,
|
344
|
+
# you can also define callbacks that get triggered when you add an object to or remove an
|
345
|
+
# object from an association collection.
|
333
346
|
#
|
334
347
|
# class Project
|
335
348
|
# has_and_belongs_to_many :developers, :after_add => :evaluate_velocity
|
@@ -342,19 +355,21 @@ module ActiveRecord
|
|
342
355
|
# It's possible to stack callbacks by passing them as an array. Example:
|
343
356
|
#
|
344
357
|
# class Project
|
345
|
-
# has_and_belongs_to_many :developers,
|
358
|
+
# has_and_belongs_to_many :developers,
|
359
|
+
# :after_add => [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}]
|
346
360
|
# end
|
347
361
|
#
|
348
362
|
# Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
|
349
363
|
#
|
350
|
-
# Should any of the +before_add+ callbacks throw an exception, the object does not get
|
351
|
-
# the +before_remove+ callbacks; if an exception is
|
364
|
+
# Should any of the +before_add+ callbacks throw an exception, the object does not get
|
365
|
+
# added to the collection. Same with the +before_remove+ callbacks; if an exception is
|
366
|
+
# thrown the object doesn't get removed.
|
352
367
|
#
|
353
368
|
# === Association extensions
|
354
369
|
#
|
355
|
-
# The proxy objects that control the access to associations can be extended through anonymous
|
356
|
-
# beneficial for adding new finders, creators, and other
|
357
|
-
#
|
370
|
+
# The proxy objects that control the access to associations can be extended through anonymous
|
371
|
+
# modules. This is especially beneficial for adding new finders, creators, and other
|
372
|
+
# factory-type methods that are only used as part of this association.
|
358
373
|
#
|
359
374
|
# class Account < ActiveRecord::Base
|
360
375
|
# has_many :people do
|
@@ -369,7 +384,8 @@ module ActiveRecord
|
|
369
384
|
# person.first_name # => "David"
|
370
385
|
# person.last_name # => "Heinemeier Hansson"
|
371
386
|
#
|
372
|
-
# If you need to share the same extensions between many associations, you can use a named
|
387
|
+
# If you need to share the same extensions between many associations, you can use a named
|
388
|
+
# extension module.
|
373
389
|
#
|
374
390
|
# module FindOrCreateByNameExtension
|
375
391
|
# def find_or_create_by_name(name)
|
@@ -386,9 +402,10 @@ module ActiveRecord
|
|
386
402
|
# has_many :people, :extend => FindOrCreateByNameExtension
|
387
403
|
# end
|
388
404
|
#
|
389
|
-
# If you need to use multiple named extension modules, you can specify an array of modules
|
390
|
-
#
|
391
|
-
#
|
405
|
+
# If you need to use multiple named extension modules, you can specify an array of modules
|
406
|
+
# with the <tt>:extend</tt> option.
|
407
|
+
# In the case of name conflicts between methods in the modules, methods in modules later
|
408
|
+
# in the array supercede those earlier in the array.
|
392
409
|
#
|
393
410
|
# class Account < ActiveRecord::Base
|
394
411
|
# has_many :people, :extend => [FindOrCreateByNameExtension, FindRecentExtension]
|
@@ -399,12 +416,14 @@ module ActiveRecord
|
|
399
416
|
#
|
400
417
|
# * +proxy_owner+ - Returns the object the association is part of.
|
401
418
|
# * +proxy_reflection+ - Returns the reflection object that describes the association.
|
402
|
-
# * +proxy_target+ - Returns the associated object for +belongs_to+ and +has_one+, or
|
419
|
+
# * +proxy_target+ - Returns the associated object for +belongs_to+ and +has_one+, or
|
420
|
+
# the collection of associated objects for +has_many+ and +has_and_belongs_to_many+.
|
403
421
|
#
|
404
422
|
# === Association Join Models
|
405
423
|
#
|
406
|
-
# Has Many associations can be configured with the <tt>:through</tt> option to use an
|
407
|
-
#
|
424
|
+
# Has Many associations can be configured with the <tt>:through</tt> option to use an
|
425
|
+
# explicit join model to retrieve the data. This operates similarly to a
|
426
|
+
# +has_and_belongs_to_many+ association. The advantage is that you're able to add validations,
|
408
427
|
# callbacks, and extra attributes on the join model. Consider the following schema:
|
409
428
|
#
|
410
429
|
# class Author < ActiveRecord::Base
|
@@ -418,7 +437,7 @@ module ActiveRecord
|
|
418
437
|
# end
|
419
438
|
#
|
420
439
|
# @author = Author.find :first
|
421
|
-
# @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to
|
440
|
+
# @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to
|
422
441
|
# @author.books # selects all books by using the Authorship join model
|
423
442
|
#
|
424
443
|
# You can also go through a +has_many+ association on the join model:
|
@@ -439,7 +458,7 @@ module ActiveRecord
|
|
439
458
|
#
|
440
459
|
# @firm = Firm.find :first
|
441
460
|
# @firm.clients.collect { |c| c.invoices }.flatten # select all invoices for all clients of the firm
|
442
|
-
# @firm.invoices # selects all invoices by going through the Client join model
|
461
|
+
# @firm.invoices # selects all invoices by going through the Client join model
|
443
462
|
#
|
444
463
|
# Similarly you can go through a +has_one+ association on the join model:
|
445
464
|
#
|
@@ -461,16 +480,18 @@ module ActiveRecord
|
|
461
480
|
# @group.users.collect { |u| u.avatar }.flatten # select all avatars for all users in the group
|
462
481
|
# @group.avatars # selects all avatars by going through the User join model.
|
463
482
|
#
|
464
|
-
# An important caveat with going through +has_one+ or +has_many+ associations on the
|
465
|
-
# *read-only*. For example, the following
|
483
|
+
# An important caveat with going through +has_one+ or +has_many+ associations on the
|
484
|
+
# join model is that these associations are *read-only*. For example, the following
|
485
|
+
# would not work following the previous example:
|
466
486
|
#
|
467
|
-
# @group.avatars << Avatar.new
|
487
|
+
# @group.avatars << Avatar.new # this would work if User belonged_to Avatar rather than the other way around
|
468
488
|
# @group.avatars.delete(@group.avatars.last) # so would this
|
469
489
|
#
|
470
490
|
# === Polymorphic Associations
|
471
491
|
#
|
472
|
-
# Polymorphic associations on models are not restricted on what types of models they
|
473
|
-
# specify an interface that a +has_many+ association
|
492
|
+
# Polymorphic associations on models are not restricted on what types of models they
|
493
|
+
# can be associated with. Rather, they specify an interface that a +has_many+ association
|
494
|
+
# must adhere to.
|
474
495
|
#
|
475
496
|
# class Asset < ActiveRecord::Base
|
476
497
|
# belongs_to :attachable, :polymorphic => true
|
@@ -482,13 +503,16 @@ module ActiveRecord
|
|
482
503
|
#
|
483
504
|
# @asset.attachable = @post
|
484
505
|
#
|
485
|
-
# This works by using a type column in addition to a foreign key to specify the associated
|
486
|
-
# an +attachable_id+ integer column and an
|
506
|
+
# This works by using a type column in addition to a foreign key to specify the associated
|
507
|
+
# record. In the Asset example, you'd need an +attachable_id+ integer column and an
|
508
|
+
# +attachable_type+ string column.
|
487
509
|
#
|
488
|
-
# Using polymorphic associations in combination with single table inheritance (STI) is
|
489
|
-
# for the associations to work as expected, ensure that you
|
490
|
-
#
|
491
|
-
#
|
510
|
+
# Using polymorphic associations in combination with single table inheritance (STI) is
|
511
|
+
# a little tricky. In order for the associations to work as expected, ensure that you
|
512
|
+
# store the base model for the STI models in the type column of the polymorphic
|
513
|
+
# association. To continue with the asset example above, suppose there are guest posts
|
514
|
+
# and member posts that use the posts table for STI. In this case, there must be a +type+
|
515
|
+
# column in the posts table.
|
492
516
|
#
|
493
517
|
# class Asset < ActiveRecord::Base
|
494
518
|
# belongs_to :attachable, :polymorphic => true
|
@@ -511,9 +535,10 @@ module ActiveRecord
|
|
511
535
|
#
|
512
536
|
# == Caching
|
513
537
|
#
|
514
|
-
# All of the methods are built on a simple caching principle that will keep the result
|
515
|
-
# instructed not to. The cache is even
|
516
|
-
#
|
538
|
+
# All of the methods are built on a simple caching principle that will keep the result
|
539
|
+
# of the last query around unless specifically instructed not to. The cache is even
|
540
|
+
# shared across methods to make it even cheaper to use the macro-added methods without
|
541
|
+
# worrying too much about performance at the first go.
|
517
542
|
#
|
518
543
|
# project.milestones # fetches milestones from the database
|
519
544
|
# project.milestones.size # uses the milestone cache
|
@@ -523,9 +548,10 @@ module ActiveRecord
|
|
523
548
|
#
|
524
549
|
# == Eager loading of associations
|
525
550
|
#
|
526
|
-
# Eager loading is a way to find objects of a certain class and a number of named associations.
|
527
|
-
# one of the easiest ways of to prevent the dreaded 1+N problem in which fetching 100
|
528
|
-
#
|
551
|
+
# Eager loading is a way to find objects of a certain class and a number of named associations.
|
552
|
+
# This is one of the easiest ways of to prevent the dreaded 1+N problem in which fetching 100
|
553
|
+
# posts that each need to display their author triggers 101 database queries. Through the
|
554
|
+
# use of eager loading, the 101 queries can be reduced to 2.
|
529
555
|
#
|
530
556
|
# class Post < ActiveRecord::Base
|
531
557
|
# belongs_to :author
|
@@ -540,44 +566,55 @@ module ActiveRecord
|
|
540
566
|
# puts "Last comment on: " + post.comments.first.created_on
|
541
567
|
# end
|
542
568
|
#
|
543
|
-
# To iterate over these one hundred posts, we'll generate 201 database queries. Let's
|
569
|
+
# To iterate over these one hundred posts, we'll generate 201 database queries. Let's
|
570
|
+
# first just optimize it for retrieving the author:
|
544
571
|
#
|
545
572
|
# for post in Post.find(:all, :include => :author)
|
546
573
|
#
|
547
|
-
# This references the name of the +belongs_to+ association that also used the <tt>:author</tt>
|
548
|
-
# will collect the +author_id+ from each one and load
|
574
|
+
# This references the name of the +belongs_to+ association that also used the <tt>:author</tt>
|
575
|
+
# symbol. After loading the posts, find will collect the +author_id+ from each one and load
|
576
|
+
# all the referenced authors with one query. Doing so will cut down the number of queries
|
577
|
+
# from 201 to 102.
|
549
578
|
#
|
550
579
|
# We can improve upon the situation further by referencing both associations in the finder with:
|
551
580
|
#
|
552
581
|
# for post in Post.find(:all, :include => [ :author, :comments ])
|
553
582
|
#
|
554
|
-
# This will load all comments with a single query. This reduces the total number of queries
|
555
|
-
#
|
583
|
+
# This will load all comments with a single query. This reduces the total number of queries
|
584
|
+
# to 3. More generally the number of queries will be 1 plus the number of associations
|
585
|
+
# named (except if some of the associations are polymorphic +belongs_to+ - see below).
|
556
586
|
#
|
557
587
|
# To include a deep hierarchy of associations, use a hash:
|
558
588
|
#
|
559
589
|
# for post in Post.find(:all, :include => [ :author, { :comments => { :author => :gravatar } } ])
|
560
590
|
#
|
561
|
-
# That'll grab not only all the comments but all their authors and gravatar pictures.
|
562
|
-
# symbols, arrays and hashes in any combination to describe the
|
591
|
+
# That'll grab not only all the comments but all their authors and gravatar pictures.
|
592
|
+
# You can mix and match symbols, arrays and hashes in any combination to describe the
|
593
|
+
# associations you want to load.
|
563
594
|
#
|
564
|
-
# All of this power shouldn't fool you into thinking that you can pull out huge amounts
|
565
|
-
#
|
566
|
-
#
|
595
|
+
# All of this power shouldn't fool you into thinking that you can pull out huge amounts
|
596
|
+
# of data with no performance penalty just because you've reduced the number of queries.
|
597
|
+
# The database still needs to send all the data to Active Record and it still needs to
|
598
|
+
# be processed. So it's no catch-all for performance problems, but it's a great way to
|
599
|
+
# cut down on the number of queries in a situation as the one described above.
|
567
600
|
#
|
568
|
-
# Since only one table is loaded at a time, conditions or orders cannot reference tables
|
569
|
-
#
|
601
|
+
# Since only one table is loaded at a time, conditions or orders cannot reference tables
|
602
|
+
# other than the main one. If this is the case Active Record falls back to the previously
|
603
|
+
# used LEFT OUTER JOIN based strategy. For example
|
570
604
|
#
|
571
605
|
# Post.find(:all, :include => [ :author, :comments ], :conditions => ['comments.approved = ?', true])
|
572
606
|
#
|
573
|
-
# This will result in a single SQL query with joins along the lines of:
|
574
|
-
# <tt>LEFT OUTER JOIN
|
575
|
-
#
|
576
|
-
#
|
607
|
+
# This will result in a single SQL query with joins along the lines of:
|
608
|
+
# <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt> and
|
609
|
+
# <tt>LEFT OUTER JOIN authors ON authors.id = posts.author_id</tt>. Note that using conditions
|
610
|
+
# like this can have unintended consequences.
|
611
|
+
# In the above example posts with no approved comments are not returned at all, because
|
612
|
+
# the conditions apply to the SQL statement as a whole and not just to the association.
|
613
|
+
# You must disambiguate column references for this fallback to happen, for example
|
577
614
|
# <tt>:order => "author.name DESC"</tt> will work but <tt>:order => "name DESC"</tt> will not.
|
578
615
|
#
|
579
|
-
# If you do want eager load only some members of an association it is usually more natural
|
580
|
-
# which has conditions defined on it:
|
616
|
+
# If you do want eager load only some members of an association it is usually more natural
|
617
|
+
# to <tt>:include</tt> an association which has conditions defined on it:
|
581
618
|
#
|
582
619
|
# class Post < ActiveRecord::Base
|
583
620
|
# has_many :approved_comments, :class_name => 'Comment', :conditions => ['approved = ?', true]
|
@@ -585,9 +622,11 @@ module ActiveRecord
|
|
585
622
|
#
|
586
623
|
# Post.find(:all, :include => :approved_comments)
|
587
624
|
#
|
588
|
-
# This will load posts and eager load the +approved_comments+ association, which contains
|
625
|
+
# This will load posts and eager load the +approved_comments+ association, which contains
|
626
|
+
# only those comments that have been approved.
|
589
627
|
#
|
590
|
-
# If you eager load an association with a specified <tt>:limit</tt> option, it will be ignored,
|
628
|
+
# If you eager load an association with a specified <tt>:limit</tt> option, it will be ignored,
|
629
|
+
# returning all the associated objects:
|
591
630
|
#
|
592
631
|
# class Picture < ActiveRecord::Base
|
593
632
|
# has_many :most_recent_comments, :class_name => 'Comment', :order => 'id DESC', :limit => 10
|
@@ -595,8 +634,8 @@ module ActiveRecord
|
|
595
634
|
#
|
596
635
|
# Picture.find(:first, :include => :most_recent_comments).most_recent_comments # => returns all associated comments.
|
597
636
|
#
|
598
|
-
# When eager loaded, conditions are interpolated in the context of the model class, not
|
599
|
-
# before the actual model exists.
|
637
|
+
# When eager loaded, conditions are interpolated in the context of the model class, not
|
638
|
+
# the model instance. Conditions are lazily interpolated before the actual model exists.
|
600
639
|
#
|
601
640
|
# Eager loading is supported with polymorphic associations.
|
602
641
|
#
|
@@ -608,17 +647,21 @@ module ActiveRecord
|
|
608
647
|
#
|
609
648
|
# Address.find(:all, :include => :addressable)
|
610
649
|
#
|
611
|
-
# This will execute one query to load the addresses and load the addressables with one
|
612
|
-
#
|
613
|
-
#
|
614
|
-
#
|
615
|
-
#
|
650
|
+
# This will execute one query to load the addresses and load the addressables with one
|
651
|
+
# query per addressable type.
|
652
|
+
# For example if all the addressables are either of class Person or Company then a total
|
653
|
+
# of 3 queries will be executed. The list of addressable types to load is determined on
|
654
|
+
# the back of the addresses loaded. This is not supported if Active Record has to fallback
|
655
|
+
# to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError.
|
656
|
+
# The reason is that the parent model's type is a column value so its corresponding table
|
657
|
+
# name cannot be put in the +FROM+/+JOIN+ clauses of that query.
|
616
658
|
#
|
617
659
|
# == Table Aliasing
|
618
660
|
#
|
619
|
-
# Active Record uses table aliasing in the case that a table is referenced multiple times
|
620
|
-
#
|
621
|
-
#
|
661
|
+
# Active Record uses table aliasing in the case that a table is referenced multiple times
|
662
|
+
# in a join. If a table is referenced only once, the standard table name is used. The
|
663
|
+
# second time, the table is aliased as <tt>#{reflection_name}_#{parent_table_name}</tt>.
|
664
|
+
# Indexes are appended for any more successive uses of the table name.
|
622
665
|
#
|
623
666
|
# Post.find :all, :joins => :comments
|
624
667
|
# # => SELECT ... FROM posts INNER JOIN comments ON ...
|
@@ -651,7 +694,8 @@ module ActiveRecord
|
|
651
694
|
# INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
|
652
695
|
# INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
|
653
696
|
#
|
654
|
-
# If you wish to specify your own custom joins using a <tt>:joins</tt> option, those table
|
697
|
+
# If you wish to specify your own custom joins using a <tt>:joins</tt> option, those table
|
698
|
+
# names will take precedence over the eager associations:
|
655
699
|
#
|
656
700
|
# Post.find :all, :joins => :comments, :joins => "inner join comments ..."
|
657
701
|
# # => SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
|
@@ -660,7 +704,8 @@ module ActiveRecord
|
|
660
704
|
# INNER JOIN comments special_comments_posts ...
|
661
705
|
# INNER JOIN comments ...
|
662
706
|
#
|
663
|
-
# Table aliases are automatically truncated according to the maximum length of table identifiers
|
707
|
+
# Table aliases are automatically truncated according to the maximum length of table identifiers
|
708
|
+
# according to the specific database.
|
664
709
|
#
|
665
710
|
# == Modules
|
666
711
|
#
|
@@ -676,9 +721,10 @@ module ActiveRecord
|
|
676
721
|
# end
|
677
722
|
# end
|
678
723
|
#
|
679
|
-
# When <tt>Firm#clients</tt> is called, it will in turn call
|
680
|
-
#
|
681
|
-
#
|
724
|
+
# When <tt>Firm#clients</tt> is called, it will in turn call
|
725
|
+
# <tt>MyApplication::Business::Client.find_all_by_firm_id(firm.id)</tt>.
|
726
|
+
# If you want to associate with a class in another module scope, this can be done by
|
727
|
+
# specifying the complete class name.
|
682
728
|
#
|
683
729
|
# module MyApplication
|
684
730
|
# module Business
|
@@ -694,8 +740,8 @@ module ActiveRecord
|
|
694
740
|
#
|
695
741
|
# == Bi-directional associations
|
696
742
|
#
|
697
|
-
# When you specify an association there is usually an association on the associated model
|
698
|
-
# relationship in reverse. For example, with the following models:
|
743
|
+
# When you specify an association there is usually an association on the associated model
|
744
|
+
# that specifies the same relationship in reverse. For example, with the following models:
|
699
745
|
#
|
700
746
|
# class Dungeon < ActiveRecord::Base
|
701
747
|
# has_many :traps
|
@@ -710,9 +756,11 @@ module ActiveRecord
|
|
710
756
|
# belongs_to :dungeon
|
711
757
|
# end
|
712
758
|
#
|
713
|
-
# The +traps+ association on +Dungeon+ and the the +dungeon+ association on +Trap+ are
|
714
|
-
# inverse of
|
715
|
-
#
|
759
|
+
# The +traps+ association on +Dungeon+ and the the +dungeon+ association on +Trap+ are
|
760
|
+
# the inverse of each other and the inverse of the +dungeon+ association on +EvilWizard+
|
761
|
+
# is the +evil_wizard+ association on +Dungeon+ (and vice-versa). By default,
|
762
|
+
# Active Record doesn't know anything about these inverse relationships and so no object
|
763
|
+
# loading optimisation is possible. For example:
|
716
764
|
#
|
717
765
|
# d = Dungeon.first
|
718
766
|
# t = d.traps.first
|
@@ -720,9 +768,11 @@ module ActiveRecord
|
|
720
768
|
# d.level = 10
|
721
769
|
# d.level == t.dungeon.level # => false
|
722
770
|
#
|
723
|
-
# The +Dungeon+ instances +d+ and <tt>t.dungeon</tt> in the above example refer to
|
724
|
-
#
|
725
|
-
#
|
771
|
+
# The +Dungeon+ instances +d+ and <tt>t.dungeon</tt> in the above example refer to
|
772
|
+
# the same object data from the database, but are actually different in-memory copies
|
773
|
+
# of that data. Specifying the <tt>:inverse_of</tt> option on associations lets you tell
|
774
|
+
# Active Record about inverse relationships and it will optimise object loading. For
|
775
|
+
# example, if we changed our model definitions to:
|
726
776
|
#
|
727
777
|
# class Dungeon < ActiveRecord::Base
|
728
778
|
# has_many :traps, :inverse_of => :dungeon
|
@@ -737,8 +787,8 @@ module ActiveRecord
|
|
737
787
|
# belongs_to :dungeon, :inverse_of => :evil_wizard
|
738
788
|
# end
|
739
789
|
#
|
740
|
-
# Then, from our code snippet above, +d+ and <tt>t.dungeon</tt> are actually the same
|
741
|
-
# will return +true+.
|
790
|
+
# Then, from our code snippet above, +d+ and <tt>t.dungeon</tt> are actually the same
|
791
|
+
# in-memory instance and our final <tt>d.level == t.dungeon.level</tt> will return +true+.
|
742
792
|
#
|
743
793
|
# There are limitations to <tt>:inverse_of</tt> support:
|
744
794
|
#
|
@@ -748,13 +798,13 @@ module ActiveRecord
|
|
748
798
|
#
|
749
799
|
# == Type safety with <tt>ActiveRecord::AssociationTypeMismatch</tt>
|
750
800
|
#
|
751
|
-
# If you attempt to assign an object to an association that doesn't match the inferred
|
752
|
-
# get an <tt>ActiveRecord::AssociationTypeMismatch</tt>.
|
801
|
+
# If you attempt to assign an object to an association that doesn't match the inferred
|
802
|
+
# or specified <tt>:class_name</tt>, you'll get an <tt>ActiveRecord::AssociationTypeMismatch</tt>.
|
753
803
|
#
|
754
804
|
# == Options
|
755
805
|
#
|
756
|
-
# All of the association macros can be specialized through options. This makes cases
|
757
|
-
# possible.
|
806
|
+
# All of the association macros can be specialized through options. This makes cases
|
807
|
+
# more complex than the simple and guessable ones possible.
|
758
808
|
module ClassMethods
|
759
809
|
# Specifies a one-to-many association. The following methods for retrieval and query of
|
760
810
|
# collections of associated objects will be added:
|
@@ -764,7 +814,7 @@ module ActiveRecord
|
|
764
814
|
# An empty array is returned if none are found.
|
765
815
|
# [collection<<(object, ...)]
|
766
816
|
# Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
|
767
|
-
# Note that this operation instantly fires update sql without waiting for the save or update call on the
|
817
|
+
# Note that this operation instantly fires update sql without waiting for the save or update call on the
|
768
818
|
# parent object.
|
769
819
|
# [collection.delete(object, ...)]
|
770
820
|
# Removes one or more objects from the collection by setting their foreign keys to +NULL+.
|
@@ -828,20 +878,22 @@ module ActiveRecord
|
|
828
878
|
# === Supported options
|
829
879
|
# [:class_name]
|
830
880
|
# Specify the class name of the association. Use it only if that name can't be inferred
|
831
|
-
# from the association name. So <tt>has_many :products</tt> will by default be linked
|
832
|
-
# if the real class name is SpecialProduct, you'll have to
|
881
|
+
# from the association name. So <tt>has_many :products</tt> will by default be linked
|
882
|
+
# to the Product class, but if the real class name is SpecialProduct, you'll have to
|
883
|
+
# specify it with this option.
|
833
884
|
# [:conditions]
|
834
885
|
# Specify the conditions that the associated objects must meet in order to be included as a +WHERE+
|
835
|
-
# SQL fragment, such as <tt>price > 5 AND name LIKE 'B%'</tt>. Record creations from
|
836
|
-
#
|
837
|
-
#
|
886
|
+
# SQL fragment, such as <tt>price > 5 AND name LIKE 'B%'</tt>. Record creations from
|
887
|
+
# the association are scoped if a hash is used.
|
888
|
+
# <tt>has_many :posts, :conditions => {:published => true}</tt> will create published
|
889
|
+
# posts with <tt>@blog.posts.create</tt> or <tt>@blog.posts.build</tt>.
|
838
890
|
# [:order]
|
839
891
|
# Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
|
840
892
|
# such as <tt>last_name, first_name DESC</tt>.
|
841
893
|
# [:foreign_key]
|
842
894
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
843
|
-
# of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_many+
|
844
|
-
# as the default <tt>:foreign_key</tt>.
|
895
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_many+
|
896
|
+
# association will use "person_id" as the default <tt>:foreign_key</tt>.
|
845
897
|
# [:primary_key]
|
846
898
|
# Specify the method that returns the primary key used for the association. By default this is +id+.
|
847
899
|
# [:dependent]
|
@@ -855,10 +907,12 @@ module ActiveRecord
|
|
855
907
|
#
|
856
908
|
# [:finder_sql]
|
857
909
|
# Specify a complete SQL statement to fetch the association. This is a good way to go for complex
|
858
|
-
# associations that depend on multiple tables. Note: When this option is used, +find_in_collection+
|
910
|
+
# associations that depend on multiple tables. Note: When this option is used, +find_in_collection+
|
911
|
+
# is _not_ added.
|
859
912
|
# [:counter_sql]
|
860
913
|
# Specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is
|
861
|
-
# specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by
|
914
|
+
# specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by
|
915
|
+
# replacing <tt>SELECT ... FROM</tt> with <tt>SELECT COUNT(*) FROM</tt>.
|
862
916
|
# [:extend]
|
863
917
|
# Specify a named module for extending the proxy. See "Association extensions".
|
864
918
|
# [:include]
|
@@ -866,25 +920,31 @@ module ActiveRecord
|
|
866
920
|
# [:group]
|
867
921
|
# An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
|
868
922
|
# [:having]
|
869
|
-
# Combined with +:group+ this can be used to filter the records that a <tt>GROUP BY</tt>
|
923
|
+
# Combined with +:group+ this can be used to filter the records that a <tt>GROUP BY</tt>
|
924
|
+
# returns. Uses the <tt>HAVING</tt> SQL-clause.
|
870
925
|
# [:limit]
|
871
926
|
# An integer determining the limit on the number of rows that should be returned.
|
872
927
|
# [:offset]
|
873
|
-
# An integer determining the offset from where the rows should be fetched. So at 5,
|
928
|
+
# An integer determining the offset from where the rows should be fetched. So at 5,
|
929
|
+
# it would skip the first 4 rows.
|
874
930
|
# [:select]
|
875
|
-
# By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if
|
876
|
-
# but not include the joined columns. Do not forget
|
931
|
+
# By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if
|
932
|
+
# you, for example, want to do a join but not include the joined columns. Do not forget
|
933
|
+
# to include the primary and foreign keys, otherwise it will raise an error.
|
877
934
|
# [:as]
|
878
935
|
# Specifies a polymorphic interface (See <tt>belongs_to</tt>).
|
879
936
|
# [:through]
|
880
|
-
# Specifies a join model through which to perform the query. Options for <tt>:class_name</tt>
|
881
|
-
# are ignored, as the association uses the source reflection. You
|
882
|
-
# <tt
|
883
|
-
#
|
937
|
+
# Specifies a join model through which to perform the query. Options for <tt>:class_name</tt>
|
938
|
+
# and <tt>:foreign_key</tt> are ignored, as the association uses the source reflection. You
|
939
|
+
# can only use a <tt>:through</tt> query through a <tt>belongs_to</tt>, <tt>has_one</tt>
|
940
|
+
# or <tt>has_many</tt> association on the join model. The collection of join models
|
941
|
+
# can be managed via the collection API. For example, new join models are created for
|
942
|
+
# newly associated objects, and if some are gone their rows are deleted (directly,
|
884
943
|
# no destroy callbacks are triggered).
|
885
944
|
# [:source]
|
886
|
-
# Specifies the source association name used by <tt>has_many :through</tt> queries.
|
887
|
-
#
|
945
|
+
# Specifies the source association name used by <tt>has_many :through</tt> queries.
|
946
|
+
# Only use it if the name cannot be inferred from the association.
|
947
|
+
# <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either <tt>:subscribers</tt> or
|
888
948
|
# <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
|
889
949
|
# [:source_type]
|
890
950
|
# Specifies type of the source association used by <tt>has_many :through</tt> queries where the source
|
@@ -894,14 +954,15 @@ module ActiveRecord
|
|
894
954
|
# [:readonly]
|
895
955
|
# If true, all the associated objects are readonly through the association.
|
896
956
|
# [:validate]
|
897
|
-
# If false
|
957
|
+
# If +false+, don't validate the associated objects when saving the parent object. true by default.
|
898
958
|
# [:autosave]
|
899
|
-
# If true, always save the associated objects or destroy them if marked for destruction,
|
900
|
-
# If false, never save or destroy the associated objects.
|
959
|
+
# If true, always save the associated objects or destroy them if marked for destruction,
|
960
|
+
# when saving the parent object. If false, never save or destroy the associated objects.
|
901
961
|
# By default, only save associated objects that are new records.
|
902
962
|
# [:inverse_of]
|
903
|
-
# Specifies the name of the <tt>belongs_to</tt> association on the associated object
|
904
|
-
#
|
963
|
+
# Specifies the name of the <tt>belongs_to</tt> association on the associated object
|
964
|
+
# that is the inverse of this <tt>has_many</tt> association. Does not work in combination
|
965
|
+
# with <tt>:through</tt> or <tt>:as</tt> options.
|
905
966
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
906
967
|
#
|
907
968
|
# Option examples:
|
@@ -975,19 +1036,20 @@ module ActiveRecord
|
|
975
1036
|
# [:conditions]
|
976
1037
|
# Specify the conditions that the associated object must meet in order to be included as a +WHERE+
|
977
1038
|
# SQL fragment, such as <tt>rank = 5</tt>. Record creation from the association is scoped if a hash
|
978
|
-
# is used. <tt>has_one :account, :conditions => {:enabled => true}</tt> will create
|
979
|
-
# or <tt>@company.build_account</tt>.
|
1039
|
+
# is used. <tt>has_one :account, :conditions => {:enabled => true}</tt> will create
|
1040
|
+
# an enabled account with <tt>@company.create_account</tt> or <tt>@company.build_account</tt>.
|
980
1041
|
# [:order]
|
981
1042
|
# Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
|
982
1043
|
# such as <tt>last_name, first_name DESC</tt>.
|
983
1044
|
# [:dependent]
|
984
1045
|
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
|
985
|
-
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
|
986
|
-
# object's foreign key is set to +NULL+.
|
1046
|
+
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
|
1047
|
+
# If set to <tt>:nullify</tt>, the associated object's foreign key is set to +NULL+.
|
1048
|
+
# Also, association is assigned.
|
987
1049
|
# [:foreign_key]
|
988
1050
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
989
|
-
# of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association
|
990
|
-
# as the default <tt>:foreign_key</tt>.
|
1051
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association
|
1052
|
+
# will use "person_id" as the default <tt>:foreign_key</tt>.
|
991
1053
|
# [:primary_key]
|
992
1054
|
# Specify the method that returns the primary key used for the association. By default this is +id+.
|
993
1055
|
# [:include]
|
@@ -995,15 +1057,18 @@ module ActiveRecord
|
|
995
1057
|
# [:as]
|
996
1058
|
# Specifies a polymorphic interface (See <tt>belongs_to</tt>).
|
997
1059
|
# [:select]
|
998
|
-
# By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if, for example,
|
999
|
-
# but not include the joined columns. Do not forget to include the
|
1060
|
+
# By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if, for example,
|
1061
|
+
# you want to do a join but not include the joined columns. Do not forget to include the
|
1062
|
+
# primary and foreign keys, otherwise it will raise an error.
|
1000
1063
|
# [:through]
|
1001
|
-
# Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>
|
1002
|
-
# are ignored, as the association uses the source reflection. You
|
1003
|
-
# <tt>has_one</tt> or <tt>belongs_to</tt>
|
1064
|
+
# Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>
|
1065
|
+
# and <tt>:foreign_key</tt> are ignored, as the association uses the source reflection. You
|
1066
|
+
# can only use a <tt>:through</tt> query through a <tt>has_one</tt> or <tt>belongs_to</tt>
|
1067
|
+
# association on the join model.
|
1004
1068
|
# [:source]
|
1005
|
-
# Specifies the source association name used by <tt>has_one :through</tt> queries.
|
1006
|
-
#
|
1069
|
+
# Specifies the source association name used by <tt>has_one :through</tt> queries.
|
1070
|
+
# Only use it if the name cannot be inferred from the association.
|
1071
|
+
# <tt>has_one :favorite, :through => :favorites</tt> will look for a
|
1007
1072
|
# <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
|
1008
1073
|
# [:source_type]
|
1009
1074
|
# Specifies type of the source association used by <tt>has_one :through</tt> queries where the source
|
@@ -1011,19 +1076,21 @@ module ActiveRecord
|
|
1011
1076
|
# [:readonly]
|
1012
1077
|
# If true, the associated object is readonly through the association.
|
1013
1078
|
# [:validate]
|
1014
|
-
# If false
|
1079
|
+
# If +false+, don't validate the associated object when saving the parent object. +false+ by default.
|
1015
1080
|
# [:autosave]
|
1016
|
-
# If true, always save the associated object or destroy it if marked for destruction,
|
1017
|
-
# If false, never save or destroy the associated object.
|
1081
|
+
# If true, always save the associated object or destroy it if marked for destruction,
|
1082
|
+
# when saving the parent object. If false, never save or destroy the associated object.
|
1018
1083
|
# By default, only save the associated object if it's a new record.
|
1019
1084
|
# [:inverse_of]
|
1020
|
-
# Specifies the name of the <tt>belongs_to</tt> association on the associated object
|
1021
|
-
#
|
1085
|
+
# Specifies the name of the <tt>belongs_to</tt> association on the associated object
|
1086
|
+
# that is the inverse of this <tt>has_one</tt> association. Does not work in combination
|
1087
|
+
# with <tt>:through</tt> or <tt>:as</tt> options.
|
1022
1088
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1023
1089
|
#
|
1024
1090
|
# Option examples:
|
1025
1091
|
# has_one :credit_card, :dependent => :destroy # destroys the associated credit card
|
1026
|
-
# has_one :credit_card, :dependent => :nullify # updates the associated records foreign
|
1092
|
+
# has_one :credit_card, :dependent => :nullify # updates the associated records foreign
|
1093
|
+
# # key value to NULL rather than destroying it
|
1027
1094
|
# has_one :last_comment, :class_name => "Comment", :order => "posted_on"
|
1028
1095
|
# has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'"
|
1029
1096
|
# has_one :attachment, :as => :attachable
|
@@ -1085,27 +1152,34 @@ module ActiveRecord
|
|
1085
1152
|
# Specify the conditions that the associated object must meet in order to be included as a +WHERE+
|
1086
1153
|
# SQL fragment, such as <tt>authorized = 1</tt>.
|
1087
1154
|
# [:select]
|
1088
|
-
# By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed
|
1089
|
-
#
|
1155
|
+
# By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed
|
1156
|
+
# if, for example, you want to do a join but not include the joined columns. Do not
|
1157
|
+
# forget to include the primary and foreign keys, otherwise it will raise an error.
|
1090
1158
|
# [:foreign_key]
|
1091
1159
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1092
|
-
# of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt>
|
1093
|
-
# "person_id" as the default <tt>:foreign_key</tt>. Similarly,
|
1094
|
-
# will use a foreign key
|
1160
|
+
# of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt>
|
1161
|
+
# association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
|
1162
|
+
# <tt>belongs_to :favorite_person, :class_name => "Person"</tt> will use a foreign key
|
1163
|
+
# of "favorite_person_id".
|
1095
1164
|
# [:primary_key]
|
1096
|
-
# Specify the method that returns the primary key of associated object used for the association.
|
1165
|
+
# Specify the method that returns the primary key of associated object used for the association.
|
1166
|
+
# By default this is id.
|
1097
1167
|
# [:dependent]
|
1098
1168
|
# If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
|
1099
|
-
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
|
1100
|
-
#
|
1169
|
+
# <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
|
1170
|
+
# This option should not be specified when <tt>belongs_to</tt> is used in conjunction with
|
1171
|
+
# a <tt>has_many</tt> relationship on another class because of the potential to leave
|
1101
1172
|
# orphaned records behind.
|
1102
1173
|
# [:counter_cache]
|
1103
1174
|
# Caches the number of belonging objects on the associate class through the use of +increment_counter+
|
1104
|
-
# and +decrement_counter+. The counter cache is incremented when an object of this
|
1105
|
-
#
|
1106
|
-
#
|
1107
|
-
#
|
1108
|
-
#
|
1175
|
+
# and +decrement_counter+. The counter cache is incremented when an object of this
|
1176
|
+
# class is created and decremented when it's destroyed. This requires that a column
|
1177
|
+
# named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
|
1178
|
+
# is used on the associate class (such as a Post class). You can also specify a custom counter
|
1179
|
+
# cache column by providing a column name instead of a +true+/+false+ value to this
|
1180
|
+
# option (e.g., <tt>:counter_cache => :my_custom_counter</tt>.)
|
1181
|
+
# Note: Specifying a counter cache will add it to that model's list of readonly attributes
|
1182
|
+
# using +attr_readonly+.
|
1109
1183
|
# [:include]
|
1110
1184
|
# Specify second-order associations that should be eager loaded when this object is loaded.
|
1111
1185
|
# [:polymorphic]
|
@@ -1115,17 +1189,20 @@ module ActiveRecord
|
|
1115
1189
|
# [:readonly]
|
1116
1190
|
# If true, the associated object is readonly through the association.
|
1117
1191
|
# [:validate]
|
1118
|
-
# If false
|
1192
|
+
# If +false+, don't validate the associated objects when saving the parent object. +false+ by default.
|
1119
1193
|
# [:autosave]
|
1120
|
-
# If true, always save the associated object or destroy it if marked for destruction, when
|
1194
|
+
# If true, always save the associated object or destroy it if marked for destruction, when
|
1195
|
+
# saving the parent object.
|
1121
1196
|
# If false, never save or destroy the associated object.
|
1122
1197
|
# By default, only save the associated object if it's a new record.
|
1123
1198
|
# [:touch]
|
1124
|
-
# If true, the associated object will be touched (the updated_at/on attributes set to now)
|
1125
|
-
# destroyed. If you specify a symbol, that attribute
|
1199
|
+
# If true, the associated object will be touched (the updated_at/on attributes set to now)
|
1200
|
+
# when this record is either saved or destroyed. If you specify a symbol, that attribute
|
1201
|
+
# will be updated with the current time instead of the updated_at/on attribute.
|
1126
1202
|
# [:inverse_of]
|
1127
|
-
# Specifies the name of the <tt>has_one</tt> or <tt>has_many</tt> association on the associated
|
1128
|
-
#
|
1203
|
+
# Specifies the name of the <tt>has_one</tt> or <tt>has_many</tt> association on the associated
|
1204
|
+
# object that is the inverse of this <tt>belongs_to</tt> association. Does not work in
|
1205
|
+
# combination with the <tt>:polymorphic</tt> options.
|
1129
1206
|
# See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
|
1130
1207
|
#
|
1131
1208
|
# Option examples:
|
@@ -1159,9 +1236,10 @@ module ActiveRecord
|
|
1159
1236
|
# Specifies a many-to-many relationship with another class. This associates two classes via an
|
1160
1237
|
# intermediate join table. Unless the join table is explicitly specified as an option, it is
|
1161
1238
|
# guessed using the lexical order of the class names. So a join between Developer and Project
|
1162
|
-
# will give the default join table name of "developers_projects" because "D" outranks "P".
|
1163
|
-
# is calculated using the <tt><</tt> operator for String. This
|
1164
|
-
#
|
1239
|
+
# will give the default join table name of "developers_projects" because "D" outranks "P".
|
1240
|
+
# Note that this precedence is calculated using the <tt><</tt> operator for String. This
|
1241
|
+
# means that if the strings are of different lengths, and the strings are equal when compared
|
1242
|
+
# up to the shortest length, then the longer string is considered of higher
|
1165
1243
|
# lexical precedence than the shorter one. For example, one would expect the tables "paper_boxes" and "papers"
|
1166
1244
|
# to generate a join table name of "papers_paper_boxes" because of the length of the name "paper_boxes",
|
1167
1245
|
# but it in fact generates a join table name of "paper_boxes_papers". Be aware of this caveat, and use the
|
@@ -1183,9 +1261,10 @@ module ActiveRecord
|
|
1183
1261
|
# end
|
1184
1262
|
# end
|
1185
1263
|
#
|
1186
|
-
# Deprecated: Any additional fields added to the join table will be placed as attributes when
|
1187
|
-
# +has_and_belongs_to_many+ associations. Records returned from join
|
1188
|
-
# readonly (because we can't save changes
|
1264
|
+
# Deprecated: Any additional fields added to the join table will be placed as attributes when
|
1265
|
+
# pulling records out through +has_and_belongs_to_many+ associations. Records returned from join
|
1266
|
+
# tables with additional attributes will be marked as readonly (because we can't save changes
|
1267
|
+
# to the additional attributes). It's strongly recommended that you upgrade any
|
1189
1268
|
# associations with attributes to a real join model (see introduction).
|
1190
1269
|
#
|
1191
1270
|
# Adds the following methods for retrieval and query:
|
@@ -1196,7 +1275,7 @@ module ActiveRecord
|
|
1196
1275
|
# [collection<<(object, ...)]
|
1197
1276
|
# Adds one or more objects to the collection by creating associations in the join table
|
1198
1277
|
# (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
|
1199
|
-
# Note that this operation instantly fires update sql without waiting for the save or update call on the
|
1278
|
+
# Note that this operation instantly fires update sql without waiting for the save or update call on the
|
1200
1279
|
# parent object.
|
1201
1280
|
# [collection.delete(object, ...)]
|
1202
1281
|
# Removes one or more objects from the collection by removing their associations from the join table.
|
@@ -1225,7 +1304,8 @@ module ActiveRecord
|
|
1225
1304
|
# with +attributes+ and linked to this object through the join table, but has not yet been saved.
|
1226
1305
|
# [collection.create(attributes = {})]
|
1227
1306
|
# Returns a new object of the collection type that has been instantiated
|
1228
|
-
# with +attributes+, linked to this object through the join table, and that has already been
|
1307
|
+
# with +attributes+, linked to this object through the join table, and that has already been
|
1308
|
+
# saved (if it passed the validation).
|
1229
1309
|
#
|
1230
1310
|
# (+collection+ is replaced with the symbol passed as the first argument, so
|
1231
1311
|
# <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.)
|
@@ -1260,8 +1340,9 @@ module ActiveRecord
|
|
1260
1340
|
# MUST be declared underneath any +has_and_belongs_to_many+ declaration in order to work.
|
1261
1341
|
# [:foreign_key]
|
1262
1342
|
# Specify the foreign key used for the association. By default this is guessed to be the name
|
1263
|
-
# of this class in lower-case and "_id" suffixed. So a Person class that makes
|
1264
|
-
# to Project will use "person_id" as the
|
1343
|
+
# of this class in lower-case and "_id" suffixed. So a Person class that makes
|
1344
|
+
# a +has_and_belongs_to_many+ association to Project will use "person_id" as the
|
1345
|
+
# default <tt>:foreign_key</tt>.
|
1265
1346
|
# [:association_foreign_key]
|
1266
1347
|
# Specify the foreign key used for the association on the receiving side of the association.
|
1267
1348
|
# By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
|
@@ -1269,7 +1350,8 @@ module ActiveRecord
|
|
1269
1350
|
# the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
|
1270
1351
|
# [:conditions]
|
1271
1352
|
# Specify the conditions that the associated object must meet in order to be included as a +WHERE+
|
1272
|
-
# SQL fragment, such as <tt>authorized = 1</tt>. Record creations from the association are
|
1353
|
+
# SQL fragment, such as <tt>authorized = 1</tt>. Record creations from the association are
|
1354
|
+
# scoped if a hash is used.
|
1273
1355
|
# <tt>has_many :posts, :conditions => {:published => true}</tt> will create published posts with <tt>@blog.posts.create</tt>
|
1274
1356
|
# or <tt>@blog.posts.build</tt>.
|
1275
1357
|
# [:order]
|
@@ -1281,7 +1363,8 @@ module ActiveRecord
|
|
1281
1363
|
# Overwrite the default generated SQL statement used to fetch the association with a manual statement
|
1282
1364
|
# [:counter_sql]
|
1283
1365
|
# Specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is
|
1284
|
-
# specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by
|
1366
|
+
# specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by
|
1367
|
+
# replacing <tt>SELECT ... FROM</tt> with <tt>SELECT COUNT(*) FROM</tt>.
|
1285
1368
|
# [:delete_sql]
|
1286
1369
|
# Overwrite the default generated SQL statement used to remove links between the associated
|
1287
1370
|
# classes with a manual statement.
|
@@ -1295,20 +1378,24 @@ module ActiveRecord
|
|
1295
1378
|
# [:group]
|
1296
1379
|
# An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
|
1297
1380
|
# [:having]
|
1298
|
-
# Combined with +:group+ this can be used to filter the records that a <tt>GROUP BY</tt> returns.
|
1381
|
+
# Combined with +:group+ this can be used to filter the records that a <tt>GROUP BY</tt> returns.
|
1382
|
+
# Uses the <tt>HAVING</tt> SQL-clause.
|
1299
1383
|
# [:limit]
|
1300
1384
|
# An integer determining the limit on the number of rows that should be returned.
|
1301
1385
|
# [:offset]
|
1302
|
-
# An integer determining the offset from where the rows should be fetched. So at 5,
|
1386
|
+
# An integer determining the offset from where the rows should be fetched. So at 5,
|
1387
|
+
# it would skip the first 4 rows.
|
1303
1388
|
# [:select]
|
1304
|
-
# By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if, for example,
|
1305
|
-
# but not include the joined columns. Do not forget to include the primary
|
1389
|
+
# By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if, for example,
|
1390
|
+
# you want to do a join but not include the joined columns. Do not forget to include the primary
|
1391
|
+
# and foreign keys, otherwise it will raise an error.
|
1306
1392
|
# [:readonly]
|
1307
1393
|
# If true, all the associated objects are readonly through the association.
|
1308
1394
|
# [:validate]
|
1309
|
-
# If false
|
1395
|
+
# If +false+, don't validate the associated objects when saving the parent object. +true+ by default.
|
1310
1396
|
# [:autosave]
|
1311
|
-
# If true, always save the associated objects or destroy them if marked for destruction, when
|
1397
|
+
# If true, always save the associated objects or destroy them if marked for destruction, when
|
1398
|
+
# saving the parent object.
|
1312
1399
|
# If false, never save or destroy the associated objects.
|
1313
1400
|
# By default, only save associated objects that are new records.
|
1314
1401
|
#
|
@@ -1376,7 +1463,7 @@ module ActiveRecord
|
|
1376
1463
|
association = association_instance_get(reflection.name)
|
1377
1464
|
association && association.loaded?
|
1378
1465
|
end
|
1379
|
-
|
1466
|
+
|
1380
1467
|
redefine_method("#{reflection.name}=") do |new_value|
|
1381
1468
|
association = association_instance_get(reflection.name)
|
1382
1469
|
|
@@ -1387,7 +1474,7 @@ module ActiveRecord
|
|
1387
1474
|
association.replace(new_value)
|
1388
1475
|
association_instance_set(reflection.name, new_value.nil? ? nil : association)
|
1389
1476
|
end
|
1390
|
-
|
1477
|
+
|
1391
1478
|
redefine_method("set_#{reflection.name}_target") do |target|
|
1392
1479
|
return if target.nil? and association_proxy_class == BelongsToAssociation
|
1393
1480
|
association = association_proxy_class.new(self, reflection)
|
@@ -1410,17 +1497,17 @@ module ActiveRecord
|
|
1410
1497
|
|
1411
1498
|
association
|
1412
1499
|
end
|
1413
|
-
|
1500
|
+
|
1414
1501
|
redefine_method("#{reflection.name.to_s.singularize}_ids") do
|
1415
1502
|
if send(reflection.name).loaded? || reflection.options[:finder_sql]
|
1416
|
-
send(reflection.name).map
|
1503
|
+
send(reflection.name).map { |r| r.id }
|
1417
1504
|
else
|
1418
1505
|
if reflection.through_reflection && reflection.source_reflection.belongs_to?
|
1419
1506
|
through = reflection.through_reflection
|
1420
1507
|
primary_key = reflection.source_reflection.primary_key_name
|
1421
|
-
send(through.name).select("DISTINCT #{through.quoted_table_name}.#{primary_key}").map!(
|
1508
|
+
send(through.name).select("DISTINCT #{through.quoted_table_name}.#{primary_key}").map! { |r| r.send(primary_key) }
|
1422
1509
|
else
|
1423
|
-
send(reflection.name).select("#{reflection.quoted_table_name}.#{reflection.klass.primary_key}").except(:includes).map!
|
1510
|
+
send(reflection.name).select("#{reflection.quoted_table_name}.#{reflection.klass.primary_key}").except(:includes).map! { |r| r.id }
|
1424
1511
|
end
|
1425
1512
|
end
|
1426
1513
|
end
|
@@ -1437,10 +1524,12 @@ module ActiveRecord
|
|
1437
1524
|
association.replace(new_value)
|
1438
1525
|
association
|
1439
1526
|
end
|
1440
|
-
|
1527
|
+
|
1441
1528
|
redefine_method("#{reflection.name.to_s.singularize}_ids=") do |new_value|
|
1442
|
-
|
1443
|
-
|
1529
|
+
pk_column = reflection.primary_key_column
|
1530
|
+
ids = (new_value || []).reject { |nid| nid.blank? }
|
1531
|
+
ids.map!{ |i| pk_column.type_cast(i) }
|
1532
|
+
send("#{reflection.name}=", reflection.klass.find(ids).index_by{ |r| r.id }.values_at(*ids))
|
1444
1533
|
end
|
1445
1534
|
end
|
1446
1535
|
end
|
@@ -1498,6 +1587,7 @@ module ActiveRecord
|
|
1498
1587
|
end
|
1499
1588
|
end
|
1500
1589
|
after_save(method_name)
|
1590
|
+
after_touch(method_name)
|
1501
1591
|
after_destroy(method_name)
|
1502
1592
|
end
|
1503
1593
|
|
@@ -1802,9 +1892,7 @@ module ActiveRecord
|
|
1802
1892
|
case associations
|
1803
1893
|
when Symbol, String
|
1804
1894
|
reflection = base.reflections[associations]
|
1805
|
-
|
1806
|
-
records.each { |record| record.send(reflection.name).target.uniq! }
|
1807
|
-
end
|
1895
|
+
remove_uniq_by_reflection(reflection, records)
|
1808
1896
|
when Array
|
1809
1897
|
associations.each do |association|
|
1810
1898
|
remove_duplicate_results!(base, records, association)
|
@@ -1812,6 +1900,7 @@ module ActiveRecord
|
|
1812
1900
|
when Hash
|
1813
1901
|
associations.keys.each do |name|
|
1814
1902
|
reflection = base.reflections[name]
|
1903
|
+
remove_uniq_by_reflection(reflection, records)
|
1815
1904
|
|
1816
1905
|
parent_records = []
|
1817
1906
|
records.each do |record|
|
@@ -1830,6 +1919,7 @@ module ActiveRecord
|
|
1830
1919
|
end
|
1831
1920
|
|
1832
1921
|
protected
|
1922
|
+
|
1833
1923
|
def build(associations, parent = nil, join_class = Arel::InnerJoin)
|
1834
1924
|
parent ||= @joins.last
|
1835
1925
|
case associations
|
@@ -1852,6 +1942,12 @@ module ActiveRecord
|
|
1852
1942
|
end
|
1853
1943
|
end
|
1854
1944
|
|
1945
|
+
def remove_uniq_by_reflection(reflection, records)
|
1946
|
+
if reflection && reflection.collection?
|
1947
|
+
records.each { |record| record.send(reflection.name).target.uniq! }
|
1948
|
+
end
|
1949
|
+
end
|
1950
|
+
|
1855
1951
|
def build_join_association(reflection, parent)
|
1856
1952
|
JoinAssociation.new(reflection, self, parent)
|
1857
1953
|
end
|