public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
rails / activerecord / lib / active_record / associations.rb
e8550ee0 » jeremy 2009-05-13 Cherry-pick core extensions 1 require 'active_support/core_ext/module/delegation'
2
db045dbb » dhh 2004-11-23 Initial 3 module ActiveRecord
ccea9838 » h-lame 2009-05-01 Providing support for :inve... Comment 4 class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
5 def initialize(reflection)
6 super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{reflection.class_name})")
7 end
8 end
9
fed7d334 » dhh 2006-03-27 Fixed documentation 10 class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc:
291adbd3 » technoweenie 2006-07-19 fix association exception m... 11 def initialize(owner_class_name, reflection)
12 super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class_name}")
57af961a » technoweenie 2006-03-18 Raise error when trying to ... 13 end
14 end
15
fed7d334 » dhh 2006-03-27 Fixed documentation 16 class HasManyThroughAssociationPolymorphicError < ActiveRecordError #:nodoc:
57af961a » technoweenie 2006-03-18 Raise error when trying to ... 17 def initialize(owner_class_name, reflection, source_reflection)
291adbd3 » technoweenie 2006-07-19 fix association exception m... 18 super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}'.")
57af961a » technoweenie 2006-03-18 Raise error when trying to ... 19 end
20 end
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 21
e3dab67c » technoweenie 2007-03-12 Allow a polymorphic :source... 22 class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError #:nodoc:
23 def initialize(owner_class_name, reflection, source_reflection)
24 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.")
25 end
26 end
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 27
fed7d334 » dhh 2006-03-27 Fixed documentation 28 class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc:
38bae0a9 » technoweenie 2006-03-24 Change has_many :through to... 29 def initialize(reflection)
291adbd3 » technoweenie 2006-07-19 fix association exception m... 30 through_reflection = reflection.through_reflection
31 source_reflection_names = reflection.source_reflection_names
32 source_associations = reflection.through_reflection.klass.reflect_on_all_associations.collect { |a| a.name.inspect }
6de83562 » dhh 2009-02-27 Force all internal calls to... 33 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)}?")
57af961a » technoweenie 2006-03-18 Raise error when trying to ... 34 end
35 end
36
0aa0c84c » dhh 2007-01-26 Nodoc the irrelevant (from ... 37 class HasManyThroughSourceAssociationMacroError < ActiveRecordError #:nodoc:
4d232025 » technoweenie 2006-04-05 Added descriptive error mes... 38 def initialize(reflection)
291adbd3 » technoweenie 2006-07-19 fix association exception m... 39 through_reflection = reflection.through_reflection
40 source_reflection = reflection.source_reflection
41 super("Invalid source reflection macro :#{source_reflection.macro}#{" :through" if source_reflection.options[:through]} for has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}. Use :source to specify the source reflection.")
4d232025 » technoweenie 2006-04-05 Added descriptive error mes... 42 end
43 end
44
00d6c766 » dasil003 2009-08-09 Enable has_many :through fo... 45 class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError #:nodoc:
f6b12c11 » lifo 2008-04-05 Refactor HasManyThroughAsso... 46 def initialize(owner, reflection)
47 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}.")
48 end
49 end
00d6c766 » dasil003 2009-08-09 Enable has_many :through fo... 50
0da426be » jeremy 2006-08-18 Add records to has_many :th... 51 class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc:
52 def initialize(owner, reflection)
53 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.")
54 end
55 end
56
4b639904 » jeremy 2007-10-27 Fix has_many :through delet... 57 class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc:
58 def initialize(owner, reflection)
59 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.")
60 end
61 end
62
c896d56c » cwninja 2009-03-06 Ensure self referential HAB... 63 class HasAndBelongsToManyAssociationForeignKeyNeeded < ActiveRecordError #:nodoc:
64 def initialize(reflection)
65 super("Cannot create self referential has_and_belongs_to_many association on '#{reflection.class_name rescue nil}##{reflection.name rescue nil}'. :association_foreign_key cannot be the same as the :foreign_key.")
66 end
67 end
68
fed7d334 » dhh 2006-03-27 Fixed documentation 69 class EagerLoadPolymorphicError < ActiveRecordError #:nodoc:
57af961a » technoweenie 2006-03-18 Raise error when trying to ... 70 def initialize(reflection)
291adbd3 » technoweenie 2006-07-19 fix association exception m... 71 super("Can not eagerly load the polymorphic association #{reflection.name.inspect}")
57af961a » technoweenie 2006-03-18 Raise error when trying to ... 72 end
73 end
74
c61b10b6 » technoweenie 2006-04-24 Raise error when trying to ... 75 class ReadOnlyAssociation < ActiveRecordError #:nodoc:
76 def initialize(reflection)
291adbd3 » technoweenie 2006-07-19 fix association exception m... 77 super("Can not add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.")
c61b10b6 » technoweenie 2006-04-24 Raise error when trying to ... 78 end
79 end
80
6e754551 » lifo 2008-07-28 Merge docrails changes 81 # See ActiveRecord::Associations::ClassMethods for documentation.
db045dbb » dhh 2004-11-23 Initial 82 module Associations # :nodoc:
4e50a35f » josh 2009-05-28 Break up DependencyModule's... 83 extend ActiveSupport::Concern
a2875bec » brynary 2009-05-11 Use DependencyModule for in... 84
f3651365 » amilligan 2009-03-07 Fix RDoc grammar and ensure... 85 # These classes will be loaded when associations are created.
7254d237 » josh 2008-11-24 Autoload ActiveRecord files 86 # So there is no need to eager load them.
87 autoload :AssociationCollection, 'active_record/associations/association_collection'
88 autoload :AssociationProxy, 'active_record/associations/association_proxy'
89 autoload :BelongsToAssociation, 'active_record/associations/belongs_to_association'
90 autoload :BelongsToPolymorphicAssociation, 'active_record/associations/belongs_to_polymorphic_association'
91 autoload :HasAndBelongsToManyAssociation, 'active_record/associations/has_and_belongs_to_many_association'
92 autoload :HasManyAssociation, 'active_record/associations/has_many_association'
93 autoload :HasManyThroughAssociation, 'active_record/associations/has_many_through_association'
94 autoload :HasOneAssociation, 'active_record/associations/has_one_association'
95 autoload :HasOneThroughAssociation, 'active_record/associations/has_one_through_association'
96
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 97 # Clears out the association cache
4b229d10 » dhh 2004-12-22 Added Base#clear_associatio... 98 def clear_association_cache #:nodoc:
99 self.class.reflect_on_all_associations.to_a.each do |assoc|
100 instance_variable_set "@#{assoc.name}", nil
85fbb22f » dhh 2006-09-05 Backed out of new_record? t... 101 end unless self.new_record?
4b229d10 » dhh 2004-12-22 Added Base#clear_associatio... 102 end
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 103
ec8f0458 » alloy 2009-01-31 Add support for nested obje... Comment 104 private
105 # Gets the specified association instance if it responds to :loaded?, nil otherwise.
106 def association_instance_get(name)
107 association = instance_variable_get("@#{name}")
108 association if association.respond_to?(:loaded?)
109 end
110
111 # Set the specified association instance.
112 def association_instance_set(name, association)
113 instance_variable_set("@#{name}", association)
114 end
115
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 116 # Associations are a set of macro-like class methods for tying objects together through foreign keys. They express relationships like
117 # "Project has one Project Manager" or "Project belongs to a Portfolio". Each macro adds a number of methods to the class which are
118 # specialized according to the collection or association symbol and the options hash. It works much the same way as Ruby's own <tt>attr*</tt>
db045dbb » dhh 2004-11-23 Initial 119 # methods. Example:
120 #
121 # class Project < ActiveRecord::Base
122 # belongs_to :portfolio
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 123 # has_one :project_manager
db045dbb » dhh 2004-11-23 Initial 124 # has_many :milestones
125 # has_and_belongs_to_many :categories
126 # end
127 #
128 # The project class now has the following methods (and more) to ease the traversal and manipulation of its relationships:
823554ea » dhh 2005-01-15 Added support for associati... 129 # * <tt>Project#portfolio, Project#portfolio=(portfolio), Project#portfolio.nil?</tt>
db045dbb » dhh 2004-11-23 Initial 130 # * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt>
131 # * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone),</tt>
7aa9eed8 » jeremy 2006-09-01 Deprecation: update docs. C... 132 # <tt>Project#milestones.delete(milestone), Project#milestones.find(milestone_id), Project#milestones.find(:all, options),</tt>
db045dbb » dhh 2004-11-23 Initial 133 # <tt>Project#milestones.build, Project#milestones.create</tt>
134 # * <tt>Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1),</tt>
135 # <tt>Project#categories.delete(category1)</tt>
136 #
7288fd3e » jeremy 2007-05-18 Docs: warn that association... 137 # === A word of warning
138 #
139 # Don't create associations that have the same name as instance methods of ActiveRecord::Base. Since the association
140 # adds a method with that name to its model, it will override the inherited method and break things.
dc4eec11 » lifo 2008-05-09 Merge docrails: 141 # For instance, +attributes+ and +connection+ would be bad choices for association names.
7288fd3e » jeremy 2007-05-18 Docs: warn that association... 142 #
ff6d2aae » jeremy 2007-05-30 Quickref for association me... 143 # == Auto-generated methods
db045dbb » dhh 2004-11-23 Initial 144 #
c23c9bd1 » technoweenie 2008-03-21 Allow association scoping f... 145 # === Singular associations (one-to-one)
ff6d2aae » jeremy 2007-05-30 Quickref for association me... 146 # | | belongs_to |
147 # generated methods | belongs_to | :polymorphic | has_one
148 # ----------------------------------+------------+--------------+---------
53cd102b » lifo 2009-02-24 Merge with docrails 149 # other | X | X | X
150 # other=(other) | X | X | X
151 # build_other(attributes={}) | X | | X
152 # create_other(attributes={}) | X | | X
153 # other.create!(attributes={}) | | | X
ff6d2aae » jeremy 2007-05-30 Quickref for association me... 154 #
155 # ===Collection associations (one-to-many / many-to-many)
156 # | | | has_many
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 157 # generated methods | habtm | has_many | :through
ff6d2aae » jeremy 2007-05-30 Quickref for association me... 158 # ----------------------------------+-------+----------+----------
53cd102b » lifo 2009-02-24 Merge with docrails 159 # others | X | X | X
160 # others=(other,other,...) | X | X | X
161 # other_ids | X | X | X
162 # other_ids=(id,id,...) | X | X | X
163 # others<< | X | X | X
164 # others.push | X | X | X
165 # others.concat | X | X | X
166 # others.build(attributes={}) | X | X | X
167 # others.create(attributes={}) | X | X | X
168 # others.create!(attributes={}) | X | X | X
169 # others.size | X | X | X
170 # others.length | X | X | X
171 # others.count | X | X | X
172 # others.sum(args*,&block) | X | X | X
173 # others.empty? | X | X | X
174 # others.clear | X | X | X
175 # others.delete(other,other,...) | X | X | X
176 # others.delete_all | X | X |
177 # others.destroy_all | X | X | X
178 # others.find(*args) | X | X | X
179 # others.find_first | X | |
180 # others.exists? | X | X | X
181 # others.uniq | X | X | X
182 # others.reset | X | X | X
db045dbb » dhh 2004-11-23 Initial 183 #
51d840e2 » NZKoz 2007-01-14 Improve association documen... 184 # == Cardinality and associations
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 185 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 186 # Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
aa4af60a » lifo 2008-04-04 Improve documentation. 187 # relationships between models. Each model uses an association to describe its role in
188 # the relation. The +belongs_to+ association is always used in the model that has
8296c680 » technoweenie 2007-01-22 Remove useless code in #att... 189 # the foreign key.
51d840e2 » NZKoz 2007-01-14 Improve association documen... 190 #
191 # === One-to-one
192 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 193 # Use +has_one+ in the base, and +belongs_to+ in the associated model.
51d840e2 » NZKoz 2007-01-14 Improve association documen... 194 #
195 # class Employee < ActiveRecord::Base
196 # has_one :office
197 # end
198 # class Office < ActiveRecord::Base
199 # belongs_to :employee # foreign key - employee_id
200 # end
201 #
202 # === One-to-many
203 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 204 # Use +has_many+ in the base, and +belongs_to+ in the associated model.
51d840e2 » NZKoz 2007-01-14 Improve association documen... 205 #
206 # class Manager < ActiveRecord::Base
207 # has_many :employees
208 # end
209 # class Employee < ActiveRecord::Base
8296c680 » technoweenie 2007-01-22 Remove useless code in #att... 210 # belongs_to :manager # foreign key - manager_id
51d840e2 » NZKoz 2007-01-14 Improve association documen... 211 # end
212 #
213 # === Many-to-many
214 #
215 # There are two ways to build a many-to-many relationship.
216 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 217 # The first way uses a +has_many+ association with the <tt>:through</tt> option and a join model, so
51d840e2 » NZKoz 2007-01-14 Improve association documen... 218 # there are two stages of associations.
219 #
220 # class Assignment < ActiveRecord::Base
221 # belongs_to :programmer # foreign key - programmer_id
222 # belongs_to :project # foreign key - project_id
223 # end
224 # class Programmer < ActiveRecord::Base
225 # has_many :assignments
226 # has_many :projects, :through => :assignments
227 # end
228 # class Project < ActiveRecord::Base
229 # has_many :assignments
230 # has_many :programmers, :through => :assignments
231 # end
232 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 233 # For the second way, use +has_and_belongs_to_many+ in both models. This requires a join table
51d840e2 » NZKoz 2007-01-14 Improve association documen... 234 # that has no corresponding model or primary key.
235 #
236 # class Programmer < ActiveRecord::Base
237 # has_and_belongs_to_many :projects # foreign keys in the join table
238 # end
239 # class Project < ActiveRecord::Base
240 # has_and_belongs_to_many :programmers # foreign keys in the join table
241 # end
242 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 243 # Choosing which way to build a many-to-many relationship is not always simple.
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 244 # If you need to work with the relationship model as its own entity,
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 245 # use <tt>has_many :through</tt>. Use +has_and_belongs_to_many+ when working with legacy schemas or when
51d840e2 » NZKoz 2007-01-14 Improve association documen... 246 # you never work directly with the relationship itself.
247 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 248 # == Is it a +belongs_to+ or +has_one+ association?
db045dbb » dhh 2004-11-23 Initial 249 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 250 # Both express a 1-1 relationship. The difference is mostly where to place the foreign key, which goes on the table for the class
251 # declaring the +belongs_to+ relationship. Example:
db045dbb » dhh 2004-11-23 Initial 252 #
69d8ca4c » jeremy 2006-07-07 Clearer has_one/belongs_to ... 253 # class User < ActiveRecord::Base
254 # # I reference an account.
255 # belongs_to :account
db045dbb » dhh 2004-11-23 Initial 256 # end
257 #
69d8ca4c » jeremy 2006-07-07 Clearer has_one/belongs_to ... 258 # class Account < ActiveRecord::Base
259 # # One user references me.
260 # has_one :user
db045dbb » dhh 2004-11-23 Initial 261 # end
262 #
263 # The tables for these classes could look something like:
264 #
69d8ca4c » jeremy 2006-07-07 Clearer has_one/belongs_to ... 265 # CREATE TABLE users (
db045dbb » dhh 2004-11-23 Initial 266 # id int(11) NOT NULL auto_increment,
69d8ca4c » jeremy 2006-07-07 Clearer has_one/belongs_to ... 267 # account_id int(11) default NULL,
268 # name varchar default NULL,
db045dbb » dhh 2004-11-23 Initial 269 # PRIMARY KEY (id)
270 # )
271 #
69d8ca4c » jeremy 2006-07-07 Clearer has_one/belongs_to ... 272 # CREATE TABLE accounts (
db045dbb » dhh 2004-11-23 Initial 273 # id int(11) NOT NULL auto_increment,
274 # name varchar default NULL,
275 # PRIMARY KEY (id)
276 # )
277 #
823554ea » dhh 2005-01-15 Added support for associati... 278 # == Unsaved objects and associations
279 #
7143d801 » Marcel Molina 2007-11-07 Smattering of grammatical f... 280 # You can manipulate objects and associations before they are saved to the database, but there is some special behavior you should be
823554ea » dhh 2005-01-15 Added support for associati... 281 # aware of, mostly involving the saving of associated objects.
282 #
580ec0dc » alloy 2009-07-11 Added some documentation ab... 283 # Unless you set the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>,
284 # <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association. Setting it
285 # to +true+ will _always_ save the members, whereas setting it to +false+ will
286 # _never_ save the members.
ec8f0458 » alloy 2009-01-31 Add support for nested obje... Comment 287 #
823554ea » dhh 2005-01-15 Added support for associati... 288 # === One-to-one associations
289 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 290 # * Assigning an object to a +has_one+ association automatically saves that object and the object being replaced (if there is one), in
291 # order to update their primary keys - except if the parent object is unsaved (<tt>new_record? == true</tt>).
292 # * If either of these saves fail (due to one of the objects being invalid) the assignment statement returns +false+ and the assignment
823554ea » dhh 2005-01-15 Added support for associati... 293 # is cancelled.
dc4eec11 » lifo 2008-05-09 Merge docrails: 294 # * If you wish to assign an object to a +has_one+ association without saving it, use the <tt>association.build</tt> method (documented below).
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 295 # * Assigning an object to a +belongs_to+ association does not save the object, since the foreign key field belongs on the parent. It
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 296 # does not save the parent either.
823554ea » dhh 2005-01-15 Added support for associati... 297 #
298 # === Collections
299 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 300 # * Adding an object to a collection (+has_many+ or +has_and_belongs_to_many+) automatically saves that object, except if the parent object
823554ea » dhh 2005-01-15 Added support for associati... 301 # (the owner of the collection) is not yet stored in the database.
dc4eec11 » lifo 2008-05-09 Merge docrails: 302 # * If saving any of the objects being added to a collection (via <tt>push</tt> or similar) fails, then <tt>push</tt> returns +false+.
303 # * You can add an object to a collection without automatically saving it by using the <tt>collection.build</tt> method (documented below).
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 304 # * All unsaved (<tt>new_record? == true</tt>) members of the collection are automatically saved when the parent is saved.
823554ea » dhh 2005-01-15 Added support for associati... 305 #
17f7f8a0 » dhh 2005-07-06 Made documentation ready fo... 306 # === Association callbacks
4180e57b » dhh 2005-07-04 Added callback hooks to ass... 307 #
2af36bbb » dhh 2007-12-05 Fix typos (closes #10378) 308 # Similar to the normal callbacks that hook into the lifecycle of an Active Record object, you can also define callbacks that get
7143d801 » Marcel Molina 2007-11-07 Smattering of grammatical f... 309 # triggered when you add an object to or remove an object from an association collection. Example:
4180e57b » dhh 2005-07-04 Added callback hooks to ass... 310 #
311 # class Project
312 # has_and_belongs_to_many :developers, :after_add => :evaluate_velocity
313 #
314 # def evaluate_velocity(developer)
315 # ...
316 # end
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 317 # end
4180e57b » dhh 2005-07-04 Added callback hooks to ass... 318 #
319 # It's possible to stack callbacks by passing them as an array. Example:
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 320 #
4180e57b » dhh 2005-07-04 Added callback hooks to ass... 321 # class Project
17f7f8a0 » dhh 2005-07-06 Made documentation ready fo... 322 # has_and_belongs_to_many :developers, :after_add => [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}]
4180e57b » dhh 2005-07-04 Added callback hooks to ass... 323 # end
324 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 325 # Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
4180e57b » dhh 2005-07-04 Added callback hooks to ass... 326 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 327 # Should any of the +before_add+ callbacks throw an exception, the object does not get added to the collection. Same with
328 # the +before_remove+ callbacks; if an exception is thrown the object doesn't get removed.
4180e57b » dhh 2005-07-04 Added callback hooks to ass... 329 #
8c512a1c » dhh 2005-11-03 Added extension capabilitie... 330 # === Association extensions
331 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 332 # The proxy objects that control the access to associations can be extended through anonymous modules. This is especially
3c01e01d » Marcel Molina 2005-12-19 Fix typo in association doc... 333 # beneficial for adding new finders, creators, and other factory-type methods that are only used as part of this association.
8c512a1c » dhh 2005-11-03 Added extension capabilitie... 334 # Example:
335 #
336 # class Account < ActiveRecord::Base
c8dd66fd » dhh 2005-11-06 Made association extensions... 337 # has_many :people do
8c512a1c » dhh 2005-11-03 Added extension capabilitie... 338 # def find_or_create_by_name(name)
e5d9ad3e » dhh 2005-12-12 Added option inheritance fo... 339 # first_name, last_name = name.split(" ", 2)
da7752e5 » dhh 2005-11-06 Sharper example 340 # find_or_create_by_first_name_and_last_name(first_name, last_name)
8c512a1c » dhh 2005-11-03 Added extension capabilitie... 341 # end
c8dd66fd » dhh 2005-11-06 Made association extensions... 342 # end
8c512a1c » dhh 2005-11-03 Added extension capabilitie... 343 # end
344 #
345 # person = Account.find(:first).people.find_or_create_by_name("David Heinemeier Hansson")
346 # person.first_name # => "David"
347 # person.last_name # => "Heinemeier Hansson"
348 #
c8dd66fd » dhh 2005-11-06 Made association extensions... 349 # If you need to share the same extensions between many associations, you can use a named extension module. Example:
350 #
351 # module FindOrCreateByNameExtension
352 # def find_or_create_by_name(name)
e5d9ad3e » dhh 2005-12-12 Added option inheritance fo... 353 # first_name, last_name = name.split(" ", 2)
da7752e5 » dhh 2005-11-06 Sharper example 354 # find_or_create_by_first_name_and_last_name(first_name, last_name)
c8dd66fd » dhh 2005-11-06 Made association extensions... 355 # end
356 # end
357 #
358 # class Account < ActiveRecord::Base
359 # has_many :people, :extend => FindOrCreateByNameExtension
360 # end
361 #
362 # class Company < ActiveRecord::Base
363 # has_many :people, :extend => FindOrCreateByNameExtension
364 # end
8c512a1c » dhh 2005-11-03 Added extension capabilitie... 365 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 366 # If you need to use multiple named extension modules, you can specify an array of modules with the <tt>:extend</tt> option.
7e76740d » technoweenie 2006-04-10 Allow multiple association... 367 # In the case of name conflicts between methods in the modules, methods in modules later in the array supercede
368 # those earlier in the array. Example:
369 #
370 # class Account < ActiveRecord::Base
371 # has_many :people, :extend => [FindOrCreateByNameExtension, FindRecentExtension]
372 # end
373 #
ea51d72e » technoweenie 2006-05-28 Provide Association Extensi... 374 # Some extensions can only be made to work with knowledge of the association proxy's internals.
375 # Extensions can access relevant state using accessors on the association proxy:
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 376 #
ea51d72e » technoweenie 2006-05-28 Provide Association Extensi... 377 # * +proxy_owner+ - Returns the object the association is part of.
378 # * +proxy_reflection+ - Returns the reflection object that describes the association.
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 379 # * +proxy_target+ - Returns the associated object for +belongs_to+ and +has_one+, or the collection of associated objects for +has_many+ and +has_and_belongs_to_many+.
ea51d72e » technoweenie 2006-05-28 Provide Association Extensi... 380 #
2597bd69 » technoweenie 2006-03-27 documentation for polymorph... 381 # === Association Join Models
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 382 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 383 # Has Many associations can be configured with the <tt>:through</tt> option to use an explicit join model to retrieve the data. This
384 # operates similarly to a +has_and_belongs_to_many+ association. The advantage is that you're able to add validations,
38bae0a9 » technoweenie 2006-03-24 Change has_many :through to... 385 # callbacks, and extra attributes on the join model. Consider the following schema:
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 386 #
38bae0a9 » technoweenie 2006-03-24 Change has_many :through to... 387 # class Author < ActiveRecord::Base
388 # has_many :authorships
389 # has_many :books, :through => :authorships
390 # end
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 391 #
38bae0a9 » technoweenie 2006-03-24 Change has_many :through to... 392 # class Authorship < ActiveRecord::Base
393 # belongs_to :author
394 # belongs_to :book
395 # end
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 396 #
38bae0a9 » technoweenie 2006-03-24 Change has_many :through to... 397 # @author = Author.find :first
398 # @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to.
399 # @author.books # selects all books by using the Authorship join model
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 400 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 401 # You can also go through a +has_many+ association on the join model:
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 402 #
38bae0a9 » technoweenie 2006-03-24 Change has_many :through to... 403 # class Firm < ActiveRecord::Base
404 # has_many :clients
405 # has_many :invoices, :through => :clients
406 # end
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 407 #
38bae0a9 » technoweenie 2006-03-24 Change has_many :through to... 408 # class Client < ActiveRecord::Base
409 # belongs_to :firm
410 # has_many :invoices
411 # end
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 412 #
38bae0a9 » technoweenie 2006-03-24 Change has_many :through to... 413 # class Invoice < ActiveRecord::Base
414 # belongs_to :client
415 # end
416 #
417 # @firm = Firm.find :first
418 # @firm.clients.collect { |c| c.invoices }.flatten # select all invoices for all clients of the firm
419 # @firm.invoices # selects all invoices by going through the Client join model.
420 #
00d6c766 » dasil003 2009-08-09 Enable has_many :through fo... 421 # Similarly you can go through a +has_one+ association on the join model:
422 #
423 # class Group < ActiveRecord::Base
424 # has_many :users
425 # has_many :avatars, :through => :users
426 # end
427 #
428 # class User < ActiveRecord::Base
429 # belongs_to :group
430 # has_one :avatar
431 # end
432 #
433 # class Avatar < ActiveRecord::Base
434 # belongs_to :user
435 # end
436 #
437 # @group = Group.first
438 # @group.users.collect { |u| u.avatar }.flatten # select all avatars for all users in the group
439 # @group.avatars # selects all avatars by going through the User join model.
440 #
0e2fbd80 » miloops 2009-08-10 Merge commit 'rails/master' 441 # An important caveat with going through +has_one+ or +has_many+ associations on the join model is that these associations are
00d6c766 » dasil003 2009-08-09 Enable has_many :through fo... 442 # *read-only*. For example, the following would not work following the previous example:
443 #
444 # @group.avatars << Avatar.new # this would work if User belonged_to Avatar rather than the other way around.
445 # @group.avatars.delete(@group.avatars.last) # so would this
446 #
2597bd69 » technoweenie 2006-03-27 documentation for polymorph... 447 # === Polymorphic Associations
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 448 #
449 # Polymorphic associations on models are not restricted on what types of models they can be associated with. Rather, they
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 450 # specify an interface that a +has_many+ association must adhere to.
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 451 #
2597bd69 » technoweenie 2006-03-27 documentation for polymorph... 452 # class Asset < ActiveRecord::Base
453 # belongs_to :attachable, :polymorphic => true
454 # end
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 455 #
2597bd69 » technoweenie 2006-03-27 documentation for polymorph... 456 # class Post < ActiveRecord::Base
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 457 # has_many :assets, :as => :attachable # The :as option specifies the polymorphic interface to use.
2597bd69 » technoweenie 2006-03-27 documentation for polymorph... 458 # end
459 #
460 # @asset.attachable = @post
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 461 #
2597bd69 » technoweenie 2006-03-27 documentation for polymorph... 462 # This works by using a type column in addition to a foreign key to specify the associated record. In the Asset example, you'd need
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 463 # an +attachable_id+ integer column and an +attachable_type+ string column.
2597bd69 » technoweenie 2006-03-27 documentation for polymorph... 464 #
fc7fd4c5 » dhh 2006-10-08 Docfix (closes #6040) 465 # Using polymorphic associations in combination with single table inheritance (STI) is a little tricky. In order
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 466 # for the associations to work as expected, ensure that you store the base model for the STI models in the
fc7fd4c5 » dhh 2006-10-08 Docfix (closes #6040) 467 # type column of the polymorphic association. To continue with the asset example above, suppose there are guest posts
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 468 # and member posts that use the posts table for STI. In this case, there must be a +type+ column in the posts table.
fc7fd4c5 » dhh 2006-10-08 Docfix (closes #6040) 469 #
470 # class Asset < ActiveRecord::Base
471 # belongs_to :attachable, :polymorphic => true
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 472 #
fc7fd4c5 » dhh 2006-10-08 Docfix (closes #6040) 473 # def attachable_type=(sType)
474 # super(sType.to_s.classify.constantize.base_class.to_s)
475 # end
476 # end
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 477 #
fc7fd4c5 » dhh 2006-10-08 Docfix (closes #6040) 478 # class Post < ActiveRecord::Base
479 # # because we store "Post" in attachable_type now :dependent => :destroy will work
480 # has_many :assets, :as => :attachable, :dependent => :destroy
481 # end
482 #
aa9ed408 » Marcel Molina 2007-12-05 Fix typo in documentation f... 483 # class GuestPost < Post
fc7fd4c5 » dhh 2006-10-08 Docfix (closes #6040) 484 # end
485 #
aa9ed408 » Marcel Molina 2007-12-05 Fix typo in documentation f... 486 # class MemberPost < Post
fc7fd4c5 » dhh 2006-10-08 Docfix (closes #6040) 487 # end
488 #
db045dbb » dhh 2004-11-23 Initial 489 # == Caching
490 #
491 # All of the methods are built on a simple caching principle that will keep the result of the last query around unless specifically
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 492 # instructed not to. The cache is even shared across methods to make it even cheaper to use the macro-added methods without
db045dbb » dhh 2004-11-23 Initial 493 # worrying too much about performance at the first go. Example:
494 #
495 # project.milestones # fetches milestones from the database
496 # project.milestones.size # uses the milestone cache
497 # project.milestones.empty? # uses the milestone cache
498 # project.milestones(true).size # fetches milestones from the database
499 # project.milestones # uses the milestone cache
500 #
515886a5 » dhh 2005-04-18 Added documentation for new... 501 # == Eager loading of associations
502 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 503 # Eager loading is a way to find objects of a certain class and a number of named associations. This is
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 504 # one of the easiest ways of to prevent the dreaded 1+N problem in which fetching 100 posts that each need to display their author
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 505 # triggers 101 database queries. Through the use of eager loading, the 101 queries can be reduced to 2. Example:
515886a5 » dhh 2005-04-18 Added documentation for new... 506 #
507 # class Post < ActiveRecord::Base
508 # belongs_to :author
509 # has_many :comments
510 # end
511 #
512 # Consider the following loop using the class above:
513 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 514 # for post in Post.all
515886a5 » dhh 2005-04-18 Added documentation for new... 515 # puts "Post: " + post.title
516 # puts "Written by: " + post.author.name
517 # puts "Last comment on: " + post.comments.first.created_on
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 518 # end
515886a5 » dhh 2005-04-18 Added documentation for new... 519 #
520 # To iterate over these one hundred posts, we'll generate 201 database queries. Let's first just optimize it for retrieving the author:
521 #
4e2f7bec » dhh 2005-04-19 Added documentation about :... 522 # for post in Post.find(:all, :include => :author)
515886a5 » dhh 2005-04-18 Added documentation for new... 523 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 524 # This references the name of the +belongs_to+ association that also used the <tt>:author</tt> symbol. After loading the posts, find
525 # will collect the +author_id+ from each one and load all the referenced authors with one query. Doing so will cut down the number of queries from 201 to 102.
515886a5 » dhh 2005-04-18 Added documentation for new... 526 #
527 # We can improve upon the situation further by referencing both associations in the finder with:
528 #
4e2f7bec » dhh 2005-04-19 Added documentation about :... 529 # for post in Post.find(:all, :include => [ :author, :comments ])
515886a5 » dhh 2005-04-18 Added documentation for new... 530 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 531 # This will load all comments with a single query. This reduces the total number of queries to 3. More generally the number of queries
532 # will be 1 plus the number of associations named (except if some of the associations are polymorphic +belongs_to+ - see below).
5b414190 » jeremy 2007-05-19 Document deep eager include... 533 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 534 # To include a deep hierarchy of associations, use a hash:
5b414190 » jeremy 2007-05-19 Document deep eager include... 535 #
536 # for post in Post.find(:all, :include => [ :author, { :comments => { :author => :gravatar } } ])
537 #
538 # That'll grab not only all the comments but all their authors and gravatar pictures. You can mix and match
539 # symbols, arrays and hashes in any combination to describe the associations you want to load.
540 #
541 # All of this power shouldn't fool you into thinking that you can pull out huge amounts of data with no performance penalty just because you've reduced
a8eea0b0 » dhh 2005-10-26 Fix docs (closes #2491) 542 # the number of queries. The database still needs to send all the data to Active Record and it still needs to be processed. So it's no
543 # catch-all for performance problems, but it's a great way to cut down on the number of queries in a situation as the one described above.
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 544 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 545 # Since only one table is loaded at a time, conditions or orders cannot reference tables other than the main one. If this is the case
546 # Active Record falls back to the previously used LEFT OUTER JOIN based strategy. For example
19d2ff83 » miloops 2009-04-29 Calculations now use Arel t... 547 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 548 # Post.find(:all, :include => [ :author, :comments ], :conditions => ['comments.approved = ?', true])
515886a5 » dhh 2005-04-18 Added documentation for new... 549 #
e033b5d0 » lifo 2009-07-25 Merge docrails 550 # This will result in a single SQL query with joins along the lines of: <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt> and
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 551 # <tt>LEFT OUTER JOIN authors ON authors.id = posts.author_id</tt>. Note that using conditions like this can have unintended consequences.
552 # In the above example posts with no approved comments are not returned at all, because the conditions apply to the SQL statement as a whole
553 # and not just to the association. You must disambiguate column references for this fallback to happen, for example
19d2ff83 » miloops 2009-04-29 Calculations now use Arel t... 554 # <tt>:order => "author.name DESC"</tt> will work but <tt>:order => "name DESC"</tt> will not.
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 555 #
e033b5d0 » lifo 2009-07-25 Merge docrails 556 # If you do want eager load only some members of an association it is usually more natural to <tt>:include</tt> an association
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 557 # which has conditions defined on it:
558 #
559 # class Post < ActiveRecord::Base
560 # has_many :approved_comments, :class_name => 'Comment', :conditions => ['approved = ?', true]
561 # end
562 #
563 # Post.find(:all, :include => :approved_comments)
564 #
e033b5d0 » lifo 2009-07-25 Merge docrails 565 # This will load posts and eager load the +approved_comments+ association, which contains only those comments that have been approved.
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 566 #
dc37fdc4 » lifo 2008-11-02 Merge docrails. Remove unne... 567 # If you eager load an association with a specified <tt>:limit</tt> option, it will be ignored, returning all the associated objects:
568 #
569 # class Picture < ActiveRecord::Base
570 # has_many :most_recent_comments, :class_name => 'Comment', :order => 'id DESC', :limit => 10
571 # end
572 #
573 # Picture.find(:first, :include => :most_recent_comments).most_recent_comments # => returns all associated comments.
574 #
78704946 » technoweenie 2006-10-11 Restore eager condition int... 575 # When eager loaded, conditions are interpolated in the context of the model class, not the model instance. Conditions are lazily interpolated
576 # before the actual model exists.
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 577 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 578 # Eager loading is supported with polymorphic associations.
752f633b » jeremy 2008-01-04 Document that eager loading... 579 #
580 # class Address < ActiveRecord::Base
581 # belongs_to :addressable, :polymorphic => true
582 # end
583 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 584 # A call that tries to eager load the addressable model
752f633b » jeremy 2008-01-04 Document that eager loading... 585 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 586 # Address.find(:all, :include => :addressable)
b2fa70a8 » Marcel Molina 2008-01-23 Indicate in documentation t... 587 #
e033b5d0 » lifo 2009-07-25 Merge docrails 588 # This will execute one query to load the addresses and load the addressables with one query per addressable type.
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 589 # For example if all the addressables are either of class Person or Company then a total of 3 queries will be executed. The list of
590 # addressable types to load is determined on the back of the addresses loaded. This is not supported if Active Record has to fallback
19d2ff83 » miloops 2009-04-29 Calculations now use Arel t... 591 # to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError. The reason is that the parent
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 592 # model's type is a column value so its corresponding table name cannot be put in the +FROM+/+JOIN+ clauses of that query.
752f633b » jeremy 2008-01-04 Document that eager loading... 593 #
ed10f873 » technoweenie 2006-03-22 STI associations are now al... 594 # == Table Aliasing
595 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 596 # Active Record uses table aliasing in the case that a table is referenced multiple times in a join. If a table is referenced only once,
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 597 # the standard table name is used. The second time, the table is aliased as <tt>#{reflection_name}_#{parent_table_name}</tt>. Indexes are appended
ed10f873 » technoweenie 2006-03-22 STI associations are now al... 598 # for any more successive uses of the table name.
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 599 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 600 # Post.find :all, :joins => :comments
601 # # => SELECT ... FROM posts INNER JOIN comments ON ...
602 # Post.find :all, :joins => :special_comments # STI
603 # # => SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
604 # Post.find :all, :joins => [:comments, :special_comments] # special_comments is the reflection name, posts is the parent table name
605 # # => SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 606 #
ed10f873 » technoweenie 2006-03-22 STI associations are now al... 607 # Acts as tree example:
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 608 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 609 # TreeMixin.find :all, :joins => :children
610 # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
611 # TreeMixin.find :all, :joins => {:children => :parent}
612 # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
613 # INNER JOIN parents_mixins ...
614 # TreeMixin.find :all, :joins => {:children => {:parent => :children}}
615 # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
616 # INNER JOIN parents_mixins ...
617 # INNER JOIN mixins childrens_mixins_2
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 618 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 619 # Has and Belongs to Many join tables use the same idea, but add a <tt>_join</tt> suffix:
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 620 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 621 # Post.find :all, :joins => :categories
622 # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
623 # Post.find :all, :joins => {:categories => :posts}
624 # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
625 # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
626 # Post.find :all, :joins => {:categories => {:posts => :categories}}
627 # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
628 # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
629 # INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 630 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 631 # If you wish to specify your own custom joins using a <tt>:joins</tt> option, those table names will take precedence over the eager associations:
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 632 #
98dc5827 » lifo 2008-05-25 Merge docrails. Comment 633 # Post.find :all, :joins => :comments, :joins => "inner join comments ..."
634 # # => SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
635 # Post.find :all, :joins => [:comments, :special_comments], :joins => "inner join comments ..."
636 # # => SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
637 # INNER JOIN comments special_comments_posts ...
ed10f873 » technoweenie 2006-03-22 STI associations are now al... 638 # INNER JOIN comments ...
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 639 #
ed10f873 » technoweenie 2006-03-22 STI associations are now al... 640 # Table aliases are automatically truncated according to the maximum length of table identifiers according to the specific database.
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 641 #
db045dbb » dhh 2004-11-23 Initial 642 # == Modules
643 #
644 # By default, associations will look for objects within the current module scope. Consider:
645 #
646 # module MyApplication
647 # module Business
648 # class Firm < ActiveRecord::Base
649 # has_many :clients
650 # end
651 #
0432d151 » lifo 2008-07-16 Merge with docrails. Comment 652 # class Client < ActiveRecord::Base; end
db045dbb » dhh 2004-11-23 Initial 653 # end
654 # end
655 #
0432d151 » lifo 2008-07-16 Merge with docrails. Comment 656 # When <tt>Firm#clients</tt> is called, it will in turn call <tt>MyApplication::Business::Client.find_all_by_firm_id(firm.id)</tt>.
657 # If you want to associate with a class in another module scope, this can be done by specifying the complete class name.
658 # Example:
db045dbb » dhh 2004-11-23 Initial 659 #
660 # module MyApplication
661 # module Business
662 # class Firm < ActiveRecord::Base; end
663 # end
664 #
665 # module Billing
666 # class Account < ActiveRecord::Base
667 # belongs_to :firm, :class_name => "MyApplication::Business::Firm"
668 # end
669 # end
670 # end
671 #
e033b5d0 » lifo 2009-07-25 Merge docrails 672 # == Bi-directional associations
673 #
674 # When you specify an association there is usually an association on the associated model that specifies the same
675 # relationship in reverse. For example, with the following models:
676 #
677 # class Dungeon < ActiveRecord::Base
678 # has_many :traps
679 # has_one :evil_wizard
680 # end
681 #
682 # class Trap < ActiveRecord::Base
683 # belongs_to :dungeon
684 # end
685 #
686 # class EvilWizard < ActiveRecord::Base
687 # belongs_to :dungeon
688 # end
689 #
690 # The +traps+ association on +Dungeon+ and the the +dungeon+ association on +Trap+ are the inverse of each other and the
691 # inverse of the +dungeon+ association on +EvilWizard+ is the +evil_wizard+ association on +Dungeon+ (and vice-versa). By default,
692 # +ActiveRecord+ doesn't do know anything about these inverse relationships and so no object loading optimisation is possible. For example:
693 #
694 # d = Dungeon.first
695 # t = d.traps.first
696 # d.level == t.dungeon.level # => true
697 # d.level = 10
698 # d.level == t.dungeon.level # => false
699 #
3de59e91 » miloops 2009-07-31 Merge commit 'rails/master' 700 # The +Dungeon+ instances +d+ and <tt>t.dungeon</tt> in the above example refer to the same object data from the database, but are
e033b5d0 » lifo 2009-07-25 Merge docrails 701 # actually different in-memory copies of that data. Specifying the <tt>:inverse_of</tt> option on associations lets you tell
702 # +ActiveRecord+ about inverse relationships and it will optimise object loading. For example, if we changed our model definitions to:
703 #
704 # class Dungeon < ActiveRecord::Base
705 # has_many :traps, :inverse_of => :dungeon
706 # has_one :evil_wizard, :inverse_of => :dungeon
707 # end
708 #
709 # class Trap < ActiveRecord::Base
710 # belongs_to :dungeon, :inverse_of => :traps
711 # end
712 #
713 # class EvilWizard < ActiveRecord::Base
714 # belongs_to :dungeon, :inverse_of => :evil_wizard
715 # end
716 #
717 # Then, from our code snippet above, +d+ and <tt>t.dungeon</tt> are actually the same in-memory instance and our final <tt>d.level == t.dungeon.level</tt>
718 # will return +true+.
719 #
720 # There are limitations to <tt>:inverse_of</tt> support:
721 #
722 # * does not work with <tt>:through</tt> associations.
723 # * does not work with <tt>:polymorphic</tt> associations.
724 # * for +belongs_to+ associations +has_many+ inverse associations are ignored.
725 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 726 # == Type safety with <tt>ActiveRecord::AssociationTypeMismatch</tt>
db045dbb » dhh 2004-11-23 Initial 727 #
728 # If you attempt to assign an object to an association that doesn't match the inferred or specified <tt>:class_name</tt>, you'll
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 729 # get an <tt>ActiveRecord::AssociationTypeMismatch</tt>.
db045dbb » dhh 2004-11-23 Initial 730 #
731 # == Options
732 #
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 733 # All of the association macros can be specialized through options. This makes cases more complex than the simple and guessable ones
db045dbb » dhh 2004-11-23 Initial 734 # possible.
735 module ClassMethods
6e754551 » lifo 2008-07-28 Merge docrails changes 736 # Specifies a one-to-many association. The following methods for retrieval and query of
737 # collections of associated objects will be added:
738 #
739 # [collection(force_reload = false)]
740 # Returns an array of all the associated objects.
db045dbb » dhh 2004-11-23 Initial 741 # An empty array is returned if none are found.
6e754551 » lifo 2008-07-28 Merge docrails changes 742 # [collection<<(object, ...)]
743 # Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
744 # [collection.delete(object, ...)]
745 # Removes one or more objects from the collection by setting their foreign keys to +NULL+.
a03e2b35 » lifo 2008-10-21 Merge with docrails. Also a... 746 # Objects will be in addition destroyed if they're associated with <tt>:dependent => :destroy</tt>,
747 # and deleted if they're associated with <tt>:dependent => :delete_all</tt>.
6e754551 » lifo 2008-07-28 Merge docrails changes 748 # [collection=objects]
749 # Replaces the collections content by deleting and adding objects as appropriate.
750 # [collection_singular_ids]
751 # Returns an array of the associated objects' ids
752 # [collection_singular_ids=ids]
753 # Replace the collection with the objects identified by the primary keys in +ids+
754 # [collection.clear]
755 # Removes every object from the collection. This destroys the associated objects if they
756 # are associated with <tt>:dependent => :destroy</tt>, deletes them directly from the
757 # database if <tt>:dependent => :delete_all</tt>, otherwise sets their foreign keys to +NULL+.
758 # [collection.empty?]
759 # Returns +true+ if there are no associated objects.
760 # [collection.size]
761 # Returns the number of associated objects.
762 # [collection.find(...)]
763 # Finds an associated object according to the same rules as ActiveRecord::Base.find.
c3f53f41 » lifo 2008-12-19 Merge docrails 764 # [collection.exists?(...)]
6e754551 » lifo 2008-07-28 Merge docrails changes 765 # Checks whether an associated object with the given conditions exists.
766 # Uses the same rules as ActiveRecord::Base.exists?.
767 # [collection.build(attributes = {}, ...)]
768 # Returns one or more new objects of the collection type that have been instantiated
769 # with +attributes+ and linked to this object through a foreign key, but have not yet
770 # been saved. <b>Note:</b> This only works if an associated object already exists, not if
771 # it's +nil+!
772 # [collection.create(attributes = {})]
773 # Returns a new object of the collection type that has been instantiated
774 # with +attributes+, linked to this object through a foreign key, and that has already
775 # been saved (if it passed the validation). <b>Note:</b> This only works if an associated
776 # object already exists, not if it's +nil+!
777 #
778 # (*Note*: +collection+ is replaced with the symbol passed as the first argument, so
779 # <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.)
780 #
781 # === Example
db045dbb » dhh 2004-11-23 Initial 782 #
6ef35461 » lifo 2008-09-03 Merge docrails 783 # Example: A Firm class declares <tt>has_many :clients</tt>, which will add:
784 # * <tt>Firm#clients</tt> (similar to <tt>Clients.find :all, :conditions => ["firm_id = ?", id]</tt>)
db045dbb » dhh 2004-11-23 Initial 785 # * <tt>Firm#clients<<</tt>
786 # * <tt>Firm#clients.delete</tt>
bfe6a759 » dhh 2005-06-15 Added actual database-chang... 787 # * <tt>Firm#clients=</tt>
cb0837a2 » dhh 2006-10-08 Doc fixes (closes #6325) 788 # * <tt>Firm#client_ids</tt>
bfe6a759 » dhh 2005-06-15 Added actual database-chang... 789 # * <tt>Firm#client_ids=</tt>
db045dbb » dhh 2004-11-23 Initial 790 # * <tt>Firm#clients.clear</tt>
791 # * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>)
792 # * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>)
c1611a70 » dhh 2005-04-18 Updated documentation here ... 793 # * <tt>Firm#clients.find</tt> (similar to <tt>Client.find(id, :conditions => "firm_id = #{id}")</tt>)
c3f53f41 » lifo 2008-12-19 Merge docrails 794 # * <tt>Firm#clients.exists?(:name => 'ACME')</tt> (similar to <tt>Client.exists?(:name => 'ACME', :firm_id => firm.id)</tt>)
db045dbb » dhh 2004-11-23 Initial 795 # * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>)
1d4d7217 » dhh 2005-06-21 Fixed docs #856 796 # * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>)
db045dbb » dhh 2004-11-23 Initial 797 # The declaration can also include an options hash to specialize the behavior of the association.
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 798 #
6e754551 » lifo 2008-07-28 Merge docrails changes 799 # === Supported options
800 # [:class_name]
801 # Specify the class name of the association. Use it only if that name can't be inferred
dc4eec11 » lifo 2008-05-09 Merge docrails: 802 # from the association name. So <tt>has_many :products</tt> will by default be linked to the Product class, but
803 # if the real class name is SpecialProduct, you'll have to specify it with this option.
6e754551 » lifo 2008-07-28 Merge docrails changes 804 # [:conditions]
805 # Specify the conditions that the associated objects must meet in order to be included as a +WHERE+
c23c9bd1 » technoweenie 2008-03-21 Allow association scoping f... 806 # SQL fragment, such as <tt>price > 5 AND name LIKE 'B%'</tt>. Record creations from the association are scoped if a hash
807 # is used. <tt>has_many :posts, :conditions => {:published => true}</tt> will create published posts with <tt>@blog.posts.create</tt>
808 # or <tt>@blog.posts.build</tt>.
6e754551 » lifo 2008-07-28 Merge docrails changes 809 # [:order]
810 # Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
dc4eec11 » lifo 2008-05-09 Merge docrails: 811 # such as <tt>last_name, first_name DESC</tt>.
6e754551 » lifo 2008-07-28 Merge docrails changes 812 # [:foreign_key]
813 # Specify the foreign key used for the association. By default this is guessed to be the name
dc4eec11 » lifo 2008-05-09 Merge docrails: 814 # of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_many+ association will use "person_id"
815 # as the default <tt>:foreign_key</tt>.
6e754551 » lifo 2008-07-28 Merge docrails changes 816 # [:primary_key]
817 # Specify the method that returns the primary key used for the association. By default this is +id+.
818 # [:dependent]
819 # If set to <tt>:destroy</tt> all the associated objects are destroyed
dc4eec11 » lifo 2008-05-09 Merge docrails: 820 # alongside this object by calling their +destroy+ method. If set to <tt>:delete_all</tt> all associated
821 # objects are deleted *without* calling their +destroy+ method. If set to <tt>:nullify</tt> all associated
822 # objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. *Warning:* This option is ignored when also using
823 # the <tt>:through</tt> option.
6e754551 » lifo 2008-07-28 Merge docrails changes 824 # [:finder_sql]
825 # Specify a complete SQL statement to fetch the association. This is a good way to go for complex
a8eea0b0 » dhh 2005-10-26 Fix docs (closes #2491) 826 # associations that depend on multiple tables. Note: When this option is used, +find_in_collection+ is _not_ added.
6e754551 » lifo 2008-07-28 Merge docrails changes 827 # [:counter_sql]
828 # Specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is
7143d801 » Marcel Molina 2007-11-07 Smattering of grammatical f... 829 # specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by replacing <tt>SELECT ... FROM</tt> with <tt>SELECT COUNT(*) FROM</tt>.
6e754551 » lifo 2008-07-28 Merge docrails changes 830 # [:extend]
831 # Specify a named module for extending the proxy. See "Association extensions".
832 # [:include]
833 # Specify second-order associations that should be eager loaded when the collection is loaded.
834 # [:group]
835 # An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
97403ad5 » miloops 2008-11-21 Add :having option to find,... 836 # [:having]
837 # Combined with +:group+ this can be used to filter the records that a <tt>GROUP BY</tt> returns. Uses the <tt>HAVING</tt> SQL-clause.
6e754551 » lifo 2008-07-28 Merge docrails changes 838 # [:limit]
839 # An integer determining the limit on the number of rows that should be returned.
840 # [:offset]
841 # An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows.
842 # [:select]
843 # By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if you, for example, want to do a join
3351d299 » indirect 2008-05-31 Add has_many :primary_key o... 844 # but not include the joined columns. Do not forget to include the primary and foreign keys, otherwise it will raise an error.
6e754551 » lifo 2008-07-28 Merge docrails changes 845 # [:as]
846 # Specifies a polymorphic interface (See <tt>belongs_to</tt>).
847 # [:through]
848 # Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt> and <tt>:foreign_key</tt>
9f51eb24 » jeremy 2007-05-22 Fix :through docs wrecked u... 849 # are ignored, as the association uses the source reflection. You can only use a <tt>:through</tt> query through a <tt>belongs_to</tt>
00d6c766 » dasil003 2009-08-09 Enable has_many :through fo... 850 # <tt>has_one</tt> or <tt>has_many</tt> association on the join model.
6e754551 » lifo 2008-07-28 Merge docrails changes 851 # [:source]
852 # Specifies the source association name used by <tt>has_many :through</tt> queries. Only use it if the name cannot be
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 853 # inferred from the association. <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either <tt>:subscribers</tt> or
dc4eec11 » lifo 2008-05-09 Merge docrails: 854 # <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
6e754551 » lifo 2008-07-28 Merge docrails changes 855 # [:source_type]
856 # Specifies type of the source association used by <tt>has_many :through</tt> queries where the source
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 857 # association is a polymorphic +belongs_to+.
6e754551 » lifo 2008-07-28 Merge docrails changes 858 # [:uniq]
859 # If true, duplicates will be omitted from the collection. Useful in conjunction with <tt>:through</tt>.
860 # [:readonly]
861 # If true, all the associated objects are readonly through the association.
862 # [:validate]
863 # If false, don't validate the associated objects when saving the parent object. true by default.
ec8f0458 » alloy 2009-01-31 Add support for nested obje... Comment 864 # [:autosave]
865 # If true, always save any loaded members and destroy members marked for destruction, when saving the parent object. Off by default.
e033b5d0 » lifo 2009-07-25 Merge docrails 866 # [:inverse_of]
3de59e91 » miloops 2009-07-31 Merge commit 'rails/master' 867 # Specifies the name of the <tt>belongs_to</tt> association on the associated object that is the inverse of this <tt>has_many</tt>
868 # association. Does not work in combination with <tt>:through</tt> or <tt>:as</tt> options.
e033b5d0 » lifo 2009-07-25 Merge docrails 869 # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional assocations for more detail.
ec8f0458 » alloy 2009-01-31 Add support for nested obje... Comment 870 #
db045dbb » dhh 2004-11-23 Initial 871 # Option examples:
872 # has_many :comments, :order => "posted_on"
49c801b7 » dhh 2005-11-06 Added :include as an option... 873 # has_many :comments, :include => :author
db045dbb » dhh 2004-11-23 Initial 874 # has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name"
57565b35 » NZKoz 2006-03-09 format fix for locking [Mic... 875 # has_many :tracks, :order => "position", :dependent => :destroy
876 # has_many :comments, :dependent => :nullify
2597bd69 » technoweenie 2006-03-27 documentation for polymorph... 877 # has_many :tags, :as => :taggable
dfa78663 » jeremy 2008-02-12 Introduce the :readonly opt... 878 # has_many :reports, :readonly => true
38bae0a9 » technoweenie 2006-03-24 Change has_many :through to... 879 # has_many :subscribers, :through => :subscriptions, :source => :user
db045dbb » dhh 2004-11-23 Initial 880 # has_many :subscribers, :class_name => "Person", :finder_sql =>
881 # 'SELECT DISTINCT people.* ' +
882 # 'FROM people p, post_subscriptions ps ' +
883 # 'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' +
884 # 'ORDER BY p.first_name'
c8dd66fd » dhh 2005-11-06 Made association extensions... 885 def has_many(association_id, options = {}, &extension)
6abda696 » dhh 2005-12-02 Added preliminary support f... 886 reflection = create_has_many_reflection(association_id, options, &extension)
887 configure_dependency_for_has_many(reflection)
f6b12c11 » lifo 2008-04-05 Refactor HasManyThroughAsso... 888 add_association_callbacks(reflection.name, reflection.options)
889
6abda696 » dhh 2005-12-02 Added preliminary support f... 890 if options[:through]
f6b12c11 » lifo 2008-04-05 Refactor HasManyThroughAsso... 891 collection_accessor_methods(reflection, HasManyThroughAssociation)
6abda696 » dhh 2005-12-02 Added preliminary support f... 892 else
893 collection_accessor_methods(reflection, HasManyAssociation)
db045dbb » dhh 2004-11-23 Initial 894 end
895 end
896
6e754551 » lifo 2008-07-28 Merge docrails changes 897 # Specifies a one-to-one association with another class. This method should only be used
898 # if the other class contains the foreign key. If the current class contains the foreign key,
899 # then you should use +belongs_to+ instead. See also ActiveRecord::Associations::ClassMethods's overview
900 # on when to use has_one and when to use belongs_to.
901 #
902 # The following methods for retrieval and query of a single associated object will be added:
903 #
904 # [association(force_reload = false)]
905 # Returns the associated object. +nil+ is returned if none is found.
906 # [association=(associate)]
907 # Assigns the associate object, extracts the primary key, sets it as the foreign key,
db045dbb » dhh 2004-11-23 Initial 908 # and saves the associate object.
6e754551 » lifo 2008-07-28 Merge docrails changes 909 # [build_association(attributes = {})]
910 # Returns a new object of the associated type that has been instantiated
911 # with +attributes+ and linked to this object through a foreign key, but has not
912 # yet been saved. <b>Note:</b> This ONLY works if an association already exists.
913 # It will NOT work if the association is +nil+.
914 # [create_association(attributes = {})]
915 # Returns a new object of the associated type that has been instantiated
916 # with +attributes+, linked to this object through a foreign key, and that
917 # has already been saved (if it passed the validation).
918 #
919 # (+association+ is replaced with the symbol passed as the first argument, so
920 # <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.)
db045dbb » dhh 2004-11-23 Initial 921 #
6e754551 » lifo 2008-07-28 Merge docrails changes 922 # === Example
923 #
924 # An Account class declares <tt>has_one :beneficiary</tt>, which will add:
3dfa56cc » dhh 2005-06-26 Updated all references to t... 925 # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.find(:first, :conditions => "account_id = #{id}")</tt>)
db045dbb » dhh 2004-11-23 Initial 926 # * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>)
3b9e90a4 » dhh 2005-04-11 Moved build_association and... 927 # * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>)
928 # * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>)
929 #
6e754551 » lifo 2008-07-28 Merge docrails changes 930 # === Options
931 #
db045dbb » dhh 2004-11-23 Initial 932 # The declaration can also include an options hash to specialize the behavior of the association.
8b5f4e47 » jeremy 2007-12-22 Ruby 1.9 compat: fix warnin... 933 #
db045dbb » dhh 2004-11-23 Initial 934 # Options are:
6e754551 » lifo 2008-07-28 Merge docrails changes 935 # [:class_name]
936 # Specify the class name of the association. Use it only if that name can't be inferred
dc4eec11 » lifo 2008-05-09 Merge docrails: 937 # from the association name. So <tt>has_one :manager</tt> will by default be linked to the Manager class, but
938 # if the real class name is Person, you'll have to specify it with this option.
6e754551 » lifo 2008-07-28 Merge docrails changes 939 # [:conditions]
940 # Specify the conditions that the associated object must meet in order to be included as a +WHERE+
4168f876 » lucianopanaro 2009-09-26 Make has_one with :conditio... 941 # SQL fragment, such as <tt>rank = 5</tt>. Record creation from the association is scoped if a hash
942 # is used. <tt>has_one :account, :conditions => {:enabled => true}</tt> will create an enabled account with <tt>@company.create_account</tt>
943 # or <tt>@company.build_account</tt>.
6e754551 » lifo 2008-07-28 Merge docrails changes 944 # [:order]
945 # Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
dc4eec11 » lifo 2008-05-09 Merge docrails: 946 # such as <tt>last_name, first_name DESC</tt>.
6e754551 » lifo 2008-07-28 Merge docrails changes 947 # [:dependent]
948 # If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
18a3333a » NZKoz 2007-08-28 Formatting, grammar and spe... 949 # <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. If set to <tt>:nullify</tt>, the associated
950 # object's foreign key is set to +NULL+. Also, association is assigned.
6e754551 » lifo 2008-07-28 Merge docrails changes 951 # [:foreign_key]
952 # Specify the foreign key used for the association. By default this is guessed to be the name
dc4eec11 » lifo 2008-05-09 Merge docrails: 953 # of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association will use "person_id"
954 # as the default <tt>:foreign_key</tt>.
6e754551 » lifo 2008-07-28 Merge docrails changes 955 # [:primary_key]