associations.rb 84.1 KB
Newer Older
1
require 'active_support/core_ext/array/wrap'
2
require 'active_support/core_ext/enumerable'
3
require 'active_support/core_ext/module/delegation'
4
require 'active_support/core_ext/object/blank'
5
require 'active_support/core_ext/string/conversions'
6
require 'active_support/core_ext/module/remove_method'
7
require 'active_support/core_ext/class/attribute'
J
Jeremy Kemper 已提交
8

D
Initial  
David Heinemeier Hansson 已提交
9
module ActiveRecord
10
  class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
11 12
    def initialize(reflection, associated_class = nil)
      super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
13 14 15
    end
  end

D
David Heinemeier Hansson 已提交
16
  class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc:
17 18
    def initialize(owner_class_name, reflection)
      super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class_name}")
19 20 21
    end
  end

22
  class HasManyThroughAssociationPolymorphicSourceError < 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}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}'.")
25 26
    end
  end
27

28 29 30 31 32 33
  class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError #:nodoc:
    def initialize(owner_class_name, reflection)
      super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
    end
  end

34 35 36 37 38
  class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError #:nodoc:
    def initialize(owner_class_name, reflection, source_reflection)
      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.")
    end
  end
39

40 41 42 43 44 45
  class HasOneThroughCantAssociateThroughCollection < ActiveRecordError #:nodoc:
    def initialize(owner_class_name, reflection, through_reflection)
      super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
    end
  end

D
David Heinemeier Hansson 已提交
46
  class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc:
47
    def initialize(reflection)
48 49 50
      through_reflection      = reflection.through_reflection
      source_reflection_names = reflection.source_reflection_names
      source_associations     = reflection.through_reflection.klass.reflect_on_all_associations.collect { |a| a.name.inspect }
51
      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)}?")
52 53 54
    end
  end

55
  class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError #:nodoc:
56 57 58 59
    def initialize(owner, reflection)
      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}.")
    end
  end
60

61 62 63 64 65 66
  class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc:
    def initialize(owner, reflection)
      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.")
    end
  end

67 68 69 70 71
  class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc:
    def initialize(owner, reflection)
      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.")
    end
  end
J
Jon Leighton 已提交
72

73 74 75 76 77
  class HasManyThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc
    def initialize(owner, reflection)
      super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
    end
  end
78

79 80 81 82 83 84
  class HasAndBelongsToManyAssociationWithPrimaryKeyError < ActiveRecordError #:nodoc:
    def initialize(reflection)
      super("Primary key is not allowed in a has_and_belongs_to_many join table (#{reflection.options[:join_table]}).")
    end
  end

85 86 87 88 89 90
  class HasAndBelongsToManyAssociationForeignKeyNeeded < ActiveRecordError #:nodoc:
    def initialize(reflection)
      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.")
    end
  end

D
David Heinemeier Hansson 已提交
91
  class EagerLoadPolymorphicError < ActiveRecordError #:nodoc:
92
    def initialize(reflection)
93
      super("Can not eagerly load the polymorphic association #{reflection.name.inspect}")
94 95 96
    end
  end

97 98
  class ReadOnlyAssociation < ActiveRecordError #:nodoc:
    def initialize(reflection)
99
      super("Can not add to a has_many :through association.  Try adding to #{reflection.through_reflection.name.inspect}.")
100 101 102
    end
  end

103
  # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
104
  # (has_many, has_one) when there is at least 1 child associated instance.
105 106
  # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
  class DeleteRestrictionError < ActiveRecordError #:nodoc:
107 108
    def initialize(name)
      super("Cannot delete record because of dependent #{name}")
109 110 111
    end
  end

P
Pratik Naik 已提交
112
  # See ActiveRecord::Associations::ClassMethods for documentation.
D
Initial  
David Heinemeier Hansson 已提交
113
  module Associations # :nodoc:
114
    extend ActiveSupport::Concern
115

116
    # These classes will be loaded when associations are created.
J
Joshua Peek 已提交
117
    # So there is no need to eager load them.
118 119 120 121 122 123
    autoload :Association,           'active_record/associations/association'
    autoload :SingularAssociation,   'active_record/associations/singular_association'
    autoload :CollectionAssociation, 'active_record/associations/collection_association'
    autoload :CollectionProxy,       'active_record/associations/collection_proxy'

    autoload :BelongsToAssociation,            'active_record/associations/belongs_to_association'
J
Joshua Peek 已提交
124
    autoload :BelongsToPolymorphicAssociation, 'active_record/associations/belongs_to_polymorphic_association'
125 126 127 128 129 130
    autoload :HasAndBelongsToManyAssociation,  'active_record/associations/has_and_belongs_to_many_association'
    autoload :HasManyAssociation,              'active_record/associations/has_many_association'
    autoload :HasManyThroughAssociation,       'active_record/associations/has_many_through_association'
    autoload :HasOneAssociation,               'active_record/associations/has_one_association'
    autoload :HasOneThroughAssociation,        'active_record/associations/has_one_through_association'
    autoload :ThroughAssociation,              'active_record/associations/through_association'
J
Joshua Peek 已提交
131

132 133 134 135 136 137 138 139 140 141 142
    module Builder #:nodoc:
      autoload :Association,           'active_record/associations/builder/association'
      autoload :SingularAssociation,   'active_record/associations/builder/singular_association'
      autoload :CollectionAssociation, 'active_record/associations/builder/collection_association'

      autoload :BelongsTo,           'active_record/associations/builder/belongs_to'
      autoload :HasOne,              'active_record/associations/builder/has_one'
      autoload :HasMany,             'active_record/associations/builder/has_many'
      autoload :HasAndBelongsToMany, 'active_record/associations/builder/has_and_belongs_to_many'
    end

143 144 145 146
    autoload :Preloader,        'active_record/associations/preloader'
    autoload :JoinDependency,   'active_record/associations/join_dependency'
    autoload :AssociationScope, 'active_record/associations/association_scope'
    autoload :AliasTracker,     'active_record/associations/alias_tracker'
147
    autoload :JoinHelper,       'active_record/associations/join_helper'
J
Joshua Peek 已提交
148

149
    # Clears out the association cache.
150
    def clear_association_cache #:nodoc:
151
      @association_cache.clear if persisted?
152
    end
153

154 155 156
    # :nodoc:
    attr_reader :association_cache

157 158 159
    # Returns the association instance for the given name, instantiating it if it doesn't already exist
    def association(name) #:nodoc:
      association = association_instance_get(name)
160

161 162 163 164
      if association.nil?
        reflection  = self.class.reflect_on_association(name)
        association = reflection.association_class.new(self, reflection)
        association_instance_set(name, association)
165 166
      end

167
      association
168
    end
169

170
    private
171
      # Returns the specified association instance if it responds to :loaded?, nil otherwise.
172
      def association_instance_get(name)
173
        @association_cache[name.to_sym]
174 175 176 177
      end

      # Set the specified association instance.
      def association_instance_set(name, association)
178
        @association_cache[name] = association
179 180
      end

181 182 183 184
    # Associations are a set of macro-like class methods for tying objects together through
    # foreign keys. They express relationships like "Project has one Project Manager"
    # or "Project belongs to a Portfolio". Each macro adds a number of methods to the
    # class which are specialized according to the collection or association symbol and the
185
    # options hash. It works much the same way as Ruby's own <tt>attr*</tt>
186
    # methods.
D
Initial  
David Heinemeier Hansson 已提交
187 188 189
    #
    #   class Project < ActiveRecord::Base
    #     belongs_to              :portfolio
190
    #     has_one                 :project_manager
D
Initial  
David Heinemeier Hansson 已提交
191 192 193 194
    #     has_many                :milestones
    #     has_and_belongs_to_many :categories
    #   end
    #
195
    # The project class now has the following methods (and more) to ease the traversal and
196
    # manipulation of its relationships:
197
    # * <tt>Project#portfolio, Project#portfolio=(portfolio), Project#portfolio.nil?</tt>
D
Initial  
David Heinemeier Hansson 已提交
198 199
    # * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt>
    # * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone),</tt>
200
    #   <tt>Project#milestones.delete(milestone), Project#milestones.find(milestone_id), Project#milestones.find(:all, options),</tt>
D
Initial  
David Heinemeier Hansson 已提交
201 202 203 204
    #   <tt>Project#milestones.build, Project#milestones.create</tt>
    # * <tt>Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1),</tt>
    #   <tt>Project#categories.delete(category1)</tt>
    #
205 206
    # === A word of warning
    #
207 208
    # Don't create associations that have the same name as instance methods of
    # <tt>ActiveRecord::Base</tt>. Since the association adds a method with that name to
209
    # its model, it will override the inherited method and break things.
P
Pratik Naik 已提交
210
    # For instance, +attributes+ and +connection+ would be bad choices for association names.
211
    #
212
    # == Auto-generated methods
D
Initial  
David Heinemeier Hansson 已提交
213
    #
214
    # === Singular associations (one-to-one)
215 216 217
    #                                     |            |  belongs_to  |
    #   generated methods                 | belongs_to | :polymorphic | has_one
    #   ----------------------------------+------------+--------------+---------
P
Pratik Naik 已提交
218 219 220 221
    #   other                             |     X      |      X       |    X
    #   other=(other)                     |     X      |      X       |    X
    #   build_other(attributes={})        |     X      |              |    X
    #   create_other(attributes={})       |     X      |              |    X
222
    #   create_other!(attributes={})      |     X      |              |    X
223 224 225
    #
    # ===Collection associations (one-to-many / many-to-many)
    #                                     |       |          | has_many
226
    #   generated methods                 | habtm | has_many | :through
227
    #   ----------------------------------+-------+----------+----------
P
Pratik Naik 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
    #   others                            |   X   |    X     |    X
    #   others=(other,other,...)          |   X   |    X     |    X
    #   other_ids                         |   X   |    X     |    X
    #   other_ids=(id,id,...)             |   X   |    X     |    X
    #   others<<                          |   X   |    X     |    X
    #   others.push                       |   X   |    X     |    X
    #   others.concat                     |   X   |    X     |    X
    #   others.build(attributes={})       |   X   |    X     |    X
    #   others.create(attributes={})      |   X   |    X     |    X
    #   others.create!(attributes={})     |   X   |    X     |    X
    #   others.size                       |   X   |    X     |    X
    #   others.length                     |   X   |    X     |    X
    #   others.count                      |   X   |    X     |    X
    #   others.sum(args*,&block)          |   X   |    X     |    X
    #   others.empty?                     |   X   |    X     |    X
    #   others.clear                      |   X   |    X     |    X
    #   others.delete(other,other,...)    |   X   |    X     |    X
245
    #   others.delete_all                 |   X   |    X     |    X
P
Pratik Naik 已提交
246 247 248 249 250
    #   others.destroy_all                |   X   |    X     |    X
    #   others.find(*args)                |   X   |    X     |    X
    #   others.exists?                    |   X   |    X     |    X
    #   others.uniq                       |   X   |    X     |    X
    #   others.reset                      |   X   |    X     |    X
D
Initial  
David Heinemeier Hansson 已提交
251
    #
252
    # == Cardinality and associations
253
    #
P
Pratik Naik 已提交
254
    # Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
P
Pratik Naik 已提交
255 256
    # relationships between models. Each model uses an association to describe its role in
    # the relation. The +belongs_to+ association is always used in the model that has
257
    # the foreign key.
258 259 260
    #
    # === One-to-one
    #
261
    # Use +has_one+ in the base, and +belongs_to+ in the associated model.
262 263 264 265 266 267 268 269 270 271
    #
    #   class Employee < ActiveRecord::Base
    #     has_one :office
    #   end
    #   class Office < ActiveRecord::Base
    #     belongs_to :employee    # foreign key - employee_id
    #   end
    #
    # === One-to-many
    #
272
    # Use +has_many+ in the base, and +belongs_to+ in the associated model.
273 274 275 276 277
    #
    #   class Manager < ActiveRecord::Base
    #     has_many :employees
    #   end
    #   class Employee < ActiveRecord::Base
278
    #     belongs_to :manager     # foreign key - manager_id
279 280 281 282 283 284
    #   end
    #
    # === Many-to-many
    #
    # There are two ways to build a many-to-many relationship.
    #
285
    # The first way uses a +has_many+ association with the <tt>:through</tt> option and a join model, so
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
    # there are two stages of associations.
    #
    #   class Assignment < ActiveRecord::Base
    #     belongs_to :programmer  # foreign key - programmer_id
    #     belongs_to :project     # foreign key - project_id
    #   end
    #   class Programmer < ActiveRecord::Base
    #     has_many :assignments
    #     has_many :projects, :through => :assignments
    #   end
    #   class Project < ActiveRecord::Base
    #     has_many :assignments
    #     has_many :programmers, :through => :assignments
    #   end
    #
301
    # For the second way, use +has_and_belongs_to_many+ in both models. This requires a join table
302 303 304 305 306 307 308 309 310
    # that has no corresponding model or primary key.
    #
    #   class Programmer < ActiveRecord::Base
    #     has_and_belongs_to_many :projects       # foreign keys in the join table
    #   end
    #   class Project < ActiveRecord::Base
    #     has_and_belongs_to_many :programmers    # foreign keys in the join table
    #   end
    #
311
    # Choosing which way to build a many-to-many relationship is not always simple.
312
    # If you need to work with the relationship model as its own entity,
313
    # use <tt>has_many :through</tt>. Use +has_and_belongs_to_many+ when working with legacy schemas or when
314 315
    # you never work directly with the relationship itself.
    #
316
    # == Is it a +belongs_to+ or +has_one+ association?
D
Initial  
David Heinemeier Hansson 已提交
317
    #
318
    # Both express a 1-1 relationship. The difference is mostly where to place the foreign
319
    # key, which goes on the table for the class declaring the +belongs_to+ relationship.
D
Initial  
David Heinemeier Hansson 已提交
320
    #
321 322 323
    #   class User < ActiveRecord::Base
    #     # I reference an account.
    #     belongs_to :account
D
Initial  
David Heinemeier Hansson 已提交
324 325
    #   end
    #
326 327 328
    #   class Account < ActiveRecord::Base
    #     # One user references me.
    #     has_one :user
D
Initial  
David Heinemeier Hansson 已提交
329 330 331 332
    #   end
    #
    # The tables for these classes could look something like:
    #
333
    #   CREATE TABLE users (
D
Initial  
David Heinemeier Hansson 已提交
334
    #     id int(11) NOT NULL auto_increment,
335 336
    #     account_id int(11) default NULL,
    #     name varchar default NULL,
D
Initial  
David Heinemeier Hansson 已提交
337 338 339
    #     PRIMARY KEY  (id)
    #   )
    #
340
    #   CREATE TABLE accounts (
D
Initial  
David Heinemeier Hansson 已提交
341 342 343 344 345
    #     id int(11) NOT NULL auto_increment,
    #     name varchar default NULL,
    #     PRIMARY KEY  (id)
    #   )
    #
346 347
    # == Unsaved objects and associations
    #
348 349
    # You can manipulate objects and associations before they are saved to the database, but
    # there is some special behavior you should be aware of, mostly involving the saving of
350
    # associated objects.
351
    #
352
    # You can set the :autosave option on a <tt>has_one</tt>, <tt>belongs_to</tt>,
353 354
    # <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association. Setting it
    # to +true+ will _always_ save the members, whereas setting it to +false+ will
355
    # _never_ save the members. More details about :autosave option is available at
356
    # autosave_association.rb .
357
    #
358 359
    # === One-to-one associations
    #
360
    # * Assigning an object to a +has_one+ association automatically saves that object and
361
    #   the object being replaced (if there is one), in order to update their foreign
362
    #   keys - except if the parent object is unsaved (<tt>new_record? == true</tt>).
363 364 365
    # * If either of these saves fail (due to one of the objects being invalid), an
    #   <tt>ActiveRecord::RecordNotSaved</tt> exception is raised and the assignment is
    #   cancelled.
366
    # * If you wish to assign an object to a +has_one+ association without saving it,
367 368
    #   use the <tt>build_association</tt> method (documented below). The object being
    #   replaced will still be saved to update its foreign key.
369
    # * Assigning an object to a +belongs_to+ association does not save the object, since
370
    #   the foreign key field belongs on the parent. It does not save the parent either.
371 372 373
    #
    # === Collections
    #
374
    # * Adding an object to a collection (+has_many+ or +has_and_belongs_to_many+) automatically
375 376
    #   saves that object, except if the parent object (the owner of the collection) is not yet
    #   stored in the database.
377
    # * If saving any of the objects being added to a collection (via <tt>push</tt> or similar)
378
    #   fails, then <tt>push</tt> returns +false+.
379 380 381
    # * If saving fails while replacing the collection (via <tt>association=</tt>), an
    #   <tt>ActiveRecord::RecordNotSaved</tt> exception is raised and the assignment is
    #   cancelled.
382
    # * You can add an object to a collection without automatically saving it by using the
383
    #   <tt>collection.build</tt> method (documented below).
384
    # * All unsaved (<tt>new_record? == true</tt>) members of the collection are automatically
385
    #   saved when the parent is saved.
386
    #
387
    # === Association callbacks
388
    #
389
    # Similar to the normal callbacks that hook into the life cycle of an Active Record object,
390
    # you can also define callbacks that get triggered when you add an object to or remove an
391
    # object from an association collection.
392 393 394 395 396 397 398
    #
    #   class Project
    #     has_and_belongs_to_many :developers, :after_add => :evaluate_velocity
    #
    #     def evaluate_velocity(developer)
    #       ...
    #     end
399
    #   end
400 401
    #
    # It's possible to stack callbacks by passing them as an array. Example:
402
    #
403
    #   class Project
404
    #     has_and_belongs_to_many :developers,
405
    #                             :after_add => [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}]
406 407
    #   end
    #
408
    # Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
409
    #
410 411
    # Should any of the +before_add+ callbacks throw an exception, the object does not get
    # added to the collection. Same with the +before_remove+ callbacks; if an exception is
412
    # thrown the object doesn't get removed.
413
    #
414 415
    # === Association extensions
    #
416 417
    # The proxy objects that control the access to associations can be extended through anonymous
    # modules. This is especially beneficial for adding new finders, creators, and other
418
    # factory-type methods that are only used as part of this association.
419 420
    #
    #   class Account < ActiveRecord::Base
421
    #     has_many :people do
422
    #       def find_or_create_by_name(name)
423
    #         first_name, last_name = name.split(" ", 2)
D
David Heinemeier Hansson 已提交
424
    #         find_or_create_by_first_name_and_last_name(first_name, last_name)
425
    #       end
426
    #     end
427 428 429 430 431 432
    #   end
    #
    #   person = Account.find(:first).people.find_or_create_by_name("David Heinemeier Hansson")
    #   person.first_name # => "David"
    #   person.last_name  # => "Heinemeier Hansson"
    #
433 434
    # If you need to share the same extensions between many associations, you can use a named
    # extension module.
435 436 437
    #
    #   module FindOrCreateByNameExtension
    #     def find_or_create_by_name(name)
438
    #       first_name, last_name = name.split(" ", 2)
D
David Heinemeier Hansson 已提交
439
    #       find_or_create_by_first_name_and_last_name(first_name, last_name)
440 441 442 443 444 445 446 447 448 449
    #     end
    #   end
    #
    #   class Account < ActiveRecord::Base
    #     has_many :people, :extend => FindOrCreateByNameExtension
    #   end
    #
    #   class Company < ActiveRecord::Base
    #     has_many :people, :extend => FindOrCreateByNameExtension
    #   end
450
    #
451
    # If you need to use multiple named extension modules, you can specify an array of modules
452
    # with the <tt>:extend</tt> option.
453 454
    # In the case of name conflicts between methods in the modules, methods in modules later
    # in the array supercede those earlier in the array.
455 456 457 458 459
    #
    #   class Account < ActiveRecord::Base
    #     has_many :people, :extend => [FindOrCreateByNameExtension, FindRecentExtension]
    #   end
    #
460 461
    # Some extensions can only be made to work with knowledge of the association proxy's internals.
    # Extensions can access relevant state using accessors on the association proxy:
462
    #
463 464
    # * +proxy_owner+ - Returns the object the association is part of.
    # * +proxy_reflection+ - Returns the reflection object that describes the association.
465
    # * +proxy_target+ - Returns the associated object for +belongs_to+ and +has_one+, or
466
    #   the collection of associated objects for +has_many+ and +has_and_belongs_to_many+.
467
    #
R
Rick Olson 已提交
468
    # === Association Join Models
469
    #
470 471
    # Has Many associations can be configured with the <tt>:through</tt> option to use an
    # explicit join model to retrieve the data.  This operates similarly to a
472
    # +has_and_belongs_to_many+ association.  The advantage is that you're able to add validations,
473
    # callbacks, and extra attributes on the join model.  Consider the following schema:
474
    #
475 476 477 478
    #   class Author < ActiveRecord::Base
    #     has_many :authorships
    #     has_many :books, :through => :authorships
    #   end
479
    #
480 481 482 483
    #   class Authorship < ActiveRecord::Base
    #     belongs_to :author
    #     belongs_to :book
    #   end
484
    #
485
    #   @author = Author.find :first
486
    #   @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to
487
    #   @author.books                              # selects all books by using the Authorship join model
488
    #
489
    # You can also go through a +has_many+ association on the join model:
490
    #
491 492 493 494
    #   class Firm < ActiveRecord::Base
    #     has_many   :clients
    #     has_many   :invoices, :through => :clients
    #   end
495
    #
496 497 498 499
    #   class Client < ActiveRecord::Base
    #     belongs_to :firm
    #     has_many   :invoices
    #   end
500
    #
501 502 503 504 505 506
    #   class Invoice < ActiveRecord::Base
    #     belongs_to :client
    #   end
    #
    #   @firm = Firm.find :first
    #   @firm.clients.collect { |c| c.invoices }.flatten # select all invoices for all clients of the firm
507
    #   @firm.invoices                                   # selects all invoices by going through the Client join model
508
    #
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528
    # Similarly you can go through a +has_one+ association on the join model:
    #
    #   class Group < ActiveRecord::Base
    #     has_many   :users
    #     has_many   :avatars, :through => :users
    #   end
    #
    #   class User < ActiveRecord::Base
    #     belongs_to :group
    #     has_one    :avatar
    #   end
    #
    #   class Avatar < ActiveRecord::Base
    #     belongs_to :user
    #   end
    #
    #   @group = Group.first
    #   @group.users.collect { |u| u.avatar }.flatten # select all avatars for all users in the group
    #   @group.avatars                                # selects all avatars by going through the User join model.
    #
529 530
    # An important caveat with going through +has_one+ or +has_many+ associations on the
    # join model is that these associations are *read-only*.  For example, the following
531
    # would not work following the previous example:
532
    #
533
    #   @group.avatars << Avatar.new   # this would work if User belonged_to Avatar rather than the other way around
534 535
    #   @group.avatars.delete(@group.avatars.last)  # so would this
    #
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
    # If you are using a +belongs_to+ on the join model, it is a good idea to set the
    # <tt>:inverse_of</tt> option on the +belongs_to+, which will mean that the following example
    # works correctly (where <tt>tags</tt> is a +has_many+ <tt>:through</tt> association):
    #
    #   @post = Post.first
    #   @tag = @post.tags.build :name => "ruby"
    #   @tag.save
    #
    # The last line ought to save the through record (a <tt>Taggable</tt>). This will only work if the
    # <tt>:inverse_of</tt> is set:
    #
    #   class Taggable < ActiveRecord::Base
    #     belongs_to :post
    #     belongs_to :tag, :inverse_of => :taggings
    #   end
    #
552
    # === Nested Associations
J
Jon Leighton 已提交
553
    #
554 555 556 557 558 559 560 561
    # You can actually specify *any* association with the <tt>:through</tt> option, including an
    # association which has a <tt>:through</tt> option itself. For example:
    #
    #   class Author < ActiveRecord::Base
    #     has_many :posts
    #     has_many :comments, :through => :posts
    #     has_many :commenters, :through => :comments
    #   end
J
Jon Leighton 已提交
562
    #
563 564 565
    #   class Post < ActiveRecord::Base
    #     has_many :comments
    #   end
J
Jon Leighton 已提交
566
    #
567 568 569
    #   class Comment < ActiveRecord::Base
    #     belongs_to :commenter
    #   end
J
Jon Leighton 已提交
570
    #
571 572 573 574 575 576 577 578 579
    #   @author = Author.first
    #   @author.commenters # => People who commented on posts written by the author
    #
    # An equivalent way of setting up this association this would be:
    #
    #   class Author < ActiveRecord::Base
    #     has_many :posts
    #     has_many :commenters, :through => :posts
    #   end
J
Jon Leighton 已提交
580
    #
581 582 583 584
    #   class Post < ActiveRecord::Base
    #     has_many :comments
    #     has_many :commenters, :through => :comments
    #   end
J
Jon Leighton 已提交
585
    #
586 587 588 589 590
    #   class Comment < ActiveRecord::Base
    #     belongs_to :commenter
    #   end
    #
    # When using nested association, you will not be able to modify the association because there
J
Jon Leighton 已提交
591
    # is not enough information to know what modification to make. For example, if you tried to
J
Jon Leighton 已提交
592
    # add a <tt>Commenter</tt> in the example above, there would be no way to tell how to set up the
593 594
    # intermediate <tt>Post</tt> and <tt>Comment</tt> objects.
    #
R
Rick Olson 已提交
595
    # === Polymorphic Associations
596
    #
597 598
    # Polymorphic associations on models are not restricted on what types of models they
    # can be associated with.  Rather, they specify an interface that a +has_many+ association
599
    # must adhere to.
600
    #
R
Rick Olson 已提交
601 602 603
    #   class Asset < ActiveRecord::Base
    #     belongs_to :attachable, :polymorphic => true
    #   end
604
    #
R
Rick Olson 已提交
605
    #   class Post < ActiveRecord::Base
606
    #     has_many :assets, :as => :attachable         # The :as option specifies the polymorphic interface to use.
R
Rick Olson 已提交
607 608 609
    #   end
    #
    #   @asset.attachable = @post
610
    #
611 612
    # 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 an +attachable_id+ integer column and an
613
    # +attachable_type+ string column.
R
Rick Olson 已提交
614
    #
615 616 617
    # Using polymorphic associations in combination with single table inheritance (STI) is
    # a little tricky. In order for the associations to work as expected, ensure that you
    # store the base model for the STI models in the type column of the polymorphic
618
    # association. To continue with the asset example above, suppose there are guest posts
619
    # and member posts that use the posts table for STI. In this case, there must be a +type+
620
    # column in the posts table.
D
David Heinemeier Hansson 已提交
621 622 623
    #
    #   class Asset < ActiveRecord::Base
    #     belongs_to :attachable, :polymorphic => true
624
    #
D
David Heinemeier Hansson 已提交
625 626 627 628
    #     def attachable_type=(sType)
    #        super(sType.to_s.classify.constantize.base_class.to_s)
    #     end
    #   end
629
    #
D
David Heinemeier Hansson 已提交
630 631 632 633 634
    #   class Post < ActiveRecord::Base
    #     # because we store "Post" in attachable_type now :dependent => :destroy will work
    #     has_many :assets, :as => :attachable, :dependent => :destroy
    #   end
    #
635
    #   class GuestPost < Post
D
David Heinemeier Hansson 已提交
636 637
    #   end
    #
638
    #   class MemberPost < Post
D
David Heinemeier Hansson 已提交
639 640
    #   end
    #
D
Initial  
David Heinemeier Hansson 已提交
641 642
    # == Caching
    #
643 644
    # All of the methods are built on a simple caching principle that will keep the result
    # of the last query around unless specifically instructed not to. The cache is even
645 646
    # shared across methods to make it even cheaper to use the macro-added methods without
    # worrying too much about performance at the first go.
D
Initial  
David Heinemeier Hansson 已提交
647 648 649 650 651 652 653
    #
    #   project.milestones             # fetches milestones from the database
    #   project.milestones.size        # uses the milestone cache
    #   project.milestones.empty?      # uses the milestone cache
    #   project.milestones(true).size  # fetches milestones from the database
    #   project.milestones             # uses the milestone cache
    #
654 655
    # == Eager loading of associations
    #
656 657 658
    # Eager loading is a way to find objects of a certain class and a number of named associations.
    # This is 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 triggers 101 database queries. Through the
659
    # use of eager loading, the 101 queries can be reduced to 2.
660 661 662 663 664 665 666 667
    #
    #   class Post < ActiveRecord::Base
    #     belongs_to :author
    #     has_many   :comments
    #   end
    #
    # Consider the following loop using the class above:
    #
P
Pratik Naik 已提交
668
    #   for post in Post.all
669 670 671
    #     puts "Post:            " + post.title
    #     puts "Written by:      " + post.author.name
    #     puts "Last comment on: " + post.comments.first.created_on
672
    #   end
673
    #
674
    # To iterate over these one hundred posts, we'll generate 201 database queries. Let's
675
    # first just optimize it for retrieving the author:
676
    #
677
    #   for post in Post.find(:all, :include => :author)
678
    #
679 680 681
    # This references the name of the +belongs_to+ association that also used the <tt>:author</tt>
    # symbol. After loading the posts, find 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
682
    # from 201 to 102.
683 684 685
    #
    # We can improve upon the situation further by referencing both associations in the finder with:
    #
686
    #   for post in Post.find(:all, :include => [ :author, :comments ])
687
    #
688 689
    # This will load all comments with a single query. This reduces the total number of queries
    # to 3. More generally the number of queries will be 1 plus the number of associations
690
    # named (except if some of the associations are polymorphic +belongs_to+ - see below).
691
    #
692
    # To include a deep hierarchy of associations, use a hash:
693 694 695
    #
    #   for post in Post.find(:all, :include => [ :author, { :comments => { :author => :gravatar } } ])
    #
696 697
    # That'll grab not only all the comments but all their authors and gravatar pictures.
    # You can mix and match symbols, arrays and hashes in any combination to describe the
698
    # associations you want to load.
699
    #
700 701 702 703
    # 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 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 catch-all for performance problems, but it's a great way to
704
    # cut down on the number of queries in a situation as the one described above.
705
    #
706 707
    # 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 Active Record falls back to the previously
708
    # used LEFT OUTER JOIN based strategy. For example
709
    #
E
Emilio Tagua 已提交
710
    #   Post.includes([:author, :comments]).where(['comments.approved = ?', true]).all
711
    #
712
    # This will result in a single SQL query with joins along the lines of:
713
    # <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt> and
714
    # <tt>LEFT OUTER JOIN authors ON authors.id = posts.author_id</tt>. Note that using conditions
715
    # like this can have unintended consequences.
716 717
    # 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 and not just to the association.
718
    # You must disambiguate column references for this fallback to happen, for example
719
    # <tt>:order => "author.name DESC"</tt> will work but <tt>:order => "name DESC"</tt> will not.
P
Pratik Naik 已提交
720
    #
721
    # If you do want eager load only some members of an association it is usually more natural
722
    # to <tt>:include</tt> an association which has conditions defined on it:
P
Pratik Naik 已提交
723 724 725 726 727 728 729
    #
    #   class Post < ActiveRecord::Base
    #     has_many :approved_comments, :class_name => 'Comment', :conditions => ['approved = ?', true]
    #   end
    #
    #   Post.find(:all, :include => :approved_comments)
    #
730
    # This will load posts and eager load the +approved_comments+ association, which contains
731
    # only those comments that have been approved.
732
    #
733
    # If you eager load an association with a specified <tt>:limit</tt> option, it will be ignored,
734
    # returning all the associated objects:
735 736 737 738 739 740 741
    #
    #   class Picture < ActiveRecord::Base
    #     has_many :most_recent_comments, :class_name => 'Comment', :order => 'id DESC', :limit => 10
    #   end
    #
    #   Picture.find(:first, :include => :most_recent_comments).most_recent_comments # => returns all associated comments.
    #
742
    # When eager loaded, conditions are interpolated in the context of the model class, not
743
    # the model instance.  Conditions are lazily interpolated before the actual model exists.
744
    #
P
Pratik Naik 已提交
745
    # Eager loading is supported with polymorphic associations.
746 747 748 749 750
    #
    #   class Address < ActiveRecord::Base
    #     belongs_to :addressable, :polymorphic => true
    #   end
    #
P
Pratik Naik 已提交
751
    # A call that tries to eager load the addressable model
752
    #
P
Pratik Naik 已提交
753
    #   Address.find(:all, :include => :addressable)
754
    #
755
    # This will execute one query to load the addresses and load the addressables with one
756
    # query per addressable type.
757 758
    # 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 addressable types to load is determined on
759
    # the back of the addresses loaded. This is not supported if Active Record has to fallback
760 761
    # to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError.
    # The reason is that the parent model's type is a column value so its corresponding table
762
    # name cannot be put in the +FROM+/+JOIN+ clauses of that query.
763
    #
764 765
    # == Table Aliasing
    #
766 767 768
    # 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, the standard table name is used.  The
    # second time, the table is aliased as <tt>#{reflection_name}_#{parent_table_name}</tt>.
769
    # Indexes are appended for any more successive uses of the table name.
770
    #
P
Pratik Naik 已提交
771 772 773 774 775 776
    #   Post.find :all, :joins => :comments
    #   # => SELECT ... FROM posts INNER JOIN comments ON ...
    #   Post.find :all, :joins => :special_comments # STI
    #   # => SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
    #   Post.find :all, :joins => [:comments, :special_comments] # special_comments is the reflection name, posts is the parent table name
    #   # => SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
777
    #
778
    # Acts as tree example:
779
    #
P
Pratik Naik 已提交
780 781 782 783 784 785 786 787 788
    #   TreeMixin.find :all, :joins => :children
    #   # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
    #   TreeMixin.find :all, :joins => {:children => :parent}
    #   # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
    #                               INNER JOIN parents_mixins ...
    #   TreeMixin.find :all, :joins => {:children => {:parent => :children}}
    #   # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
    #                               INNER JOIN parents_mixins ...
    #                               INNER JOIN mixins childrens_mixins_2
789
    #
790
    # Has and Belongs to Many join tables use the same idea, but add a <tt>_join</tt> suffix:
791
    #
P
Pratik Naik 已提交
792 793 794 795 796 797 798 799 800
    #   Post.find :all, :joins => :categories
    #   # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
    #   Post.find :all, :joins => {:categories => :posts}
    #   # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
    #                              INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
    #   Post.find :all, :joins => {:categories => {:posts => :categories}}
    #   # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
    #                              INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
    #                              INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
801
    #
802
    # If you wish to specify your own custom joins using a <tt>:joins</tt> option, those table
803
    # names will take precedence over the eager associations:
804
    #
P
Pratik Naik 已提交
805 806 807 808 809
    #   Post.find :all, :joins => :comments, :joins => "inner join comments ..."
    #   # => SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
    #   Post.find :all, :joins => [:comments, :special_comments], :joins => "inner join comments ..."
    #   # => SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
    #                              INNER JOIN comments special_comments_posts ...
810
    #                              INNER JOIN comments ...
811
    #
812
    # Table aliases are automatically truncated according to the maximum length of table identifiers
813
    # according to the specific database.
814
    #
D
Initial  
David Heinemeier Hansson 已提交
815 816 817 818 819 820 821 822 823 824
    # == Modules
    #
    # By default, associations will look for objects within the current module scope. Consider:
    #
    #   module MyApplication
    #     module Business
    #       class Firm < ActiveRecord::Base
    #          has_many :clients
    #        end
    #
P
Pratik Naik 已提交
825
    #       class Client < ActiveRecord::Base; end
D
Initial  
David Heinemeier Hansson 已提交
826 827 828
    #     end
    #   end
    #
829
    # When <tt>Firm#clients</tt> is called, it will in turn call
830
    # <tt>MyApplication::Business::Client.find_all_by_firm_id(firm.id)</tt>.
831
    # If you want to associate with a class in another module scope, this can be done by
832
    # specifying the complete class name.
D
Initial  
David Heinemeier Hansson 已提交
833 834 835 836 837 838 839 840 841 842 843 844 845
    #
    #   module MyApplication
    #     module Business
    #       class Firm < ActiveRecord::Base; end
    #     end
    #
    #     module Billing
    #       class Account < ActiveRecord::Base
    #         belongs_to :firm, :class_name => "MyApplication::Business::Firm"
    #       end
    #     end
    #   end
    #
P
Pratik Naik 已提交
846 847
    # == Bi-directional associations
    #
848
    # When you specify an association there is usually an association on the associated model
849
    # that specifies the same relationship in reverse.  For example, with the following models:
P
Pratik Naik 已提交
850 851 852 853 854 855 856 857 858 859 860 861 862 863
    #
    #    class Dungeon < ActiveRecord::Base
    #      has_many :traps
    #      has_one :evil_wizard
    #    end
    #
    #    class Trap < ActiveRecord::Base
    #      belongs_to :dungeon
    #    end
    #
    #    class EvilWizard < ActiveRecord::Base
    #      belongs_to :dungeon
    #    end
    #
864
    # The +traps+ association on +Dungeon+ and the +dungeon+ association on +Trap+ are
865
    # the inverse of each other and the inverse of the +dungeon+ association on +EvilWizard+
866
    # is the +evil_wizard+ association on +Dungeon+ (and vice-versa).  By default,
867
    # Active Record doesn't know anything about these inverse relationships and so no object
868
    # loading optimisation is possible.  For example:
P
Pratik Naik 已提交
869 870 871 872 873 874 875
    #
    #    d = Dungeon.first
    #    t = d.traps.first
    #    d.level == t.dungeon.level # => true
    #    d.level = 10
    #    d.level == t.dungeon.level # => false
    #
876 877
    # The +Dungeon+ instances +d+ and <tt>t.dungeon</tt> in the above example refer to
    # the same object data from the database, but are actually different in-memory copies
878
    # of that data.  Specifying the <tt>:inverse_of</tt> option on associations lets you tell
879
    # Active Record about inverse relationships and it will optimise object loading.  For
880
    # example, if we changed our model definitions to:
P
Pratik Naik 已提交
881 882 883 884 885 886 887 888 889 890 891 892 893 894
    #
    #    class Dungeon < ActiveRecord::Base
    #      has_many :traps, :inverse_of => :dungeon
    #      has_one :evil_wizard, :inverse_of => :dungeon
    #    end
    #
    #    class Trap < ActiveRecord::Base
    #      belongs_to :dungeon, :inverse_of => :traps
    #    end
    #
    #    class EvilWizard < ActiveRecord::Base
    #      belongs_to :dungeon, :inverse_of => :evil_wizard
    #    end
    #
895
    # Then, from our code snippet above, +d+ and <tt>t.dungeon</tt> are actually the same
896
    # in-memory instance and our final <tt>d.level == t.dungeon.level</tt> will return +true+.
P
Pratik Naik 已提交
897 898 899 900 901 902 903
    #
    # There are limitations to <tt>:inverse_of</tt> support:
    #
    # * does not work with <tt>:through</tt> associations.
    # * does not work with <tt>:polymorphic</tt> associations.
    # * for +belongs_to+ associations +has_many+ inverse associations are ignored.
    #
904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
    # == Deleting from associations
    #
    # === Dependent associations
    #
    # +has_many+, +has_one+ and +belongs_to+ associations support the <tt>:dependent</tt> option.
    # This allows you to specify that associated records should be deleted when the owner is
    # deleted.
    #
    # For example:
    #
    #     class Author
    #       has_many :posts, :dependent => :destroy
    #     end
    #     Author.find(1).destroy # => Will destroy all of the author's posts, too
    #
    # The <tt>:dependent</tt> option can have different values which specify how the deletion
    # is done. For more information, see the documentation for this option on the different
    # specific association types.
    #
    # === Delete or destroy?
    #
    # +has_many+ and +has_and_belongs_to_many+ associations have the methods <tt>destroy</tt>,
    # <tt>delete</tt>, <tt>destroy_all</tt> and <tt>delete_all</tt>.
    #
    # For +has_and_belongs_to_many+, <tt>delete</tt> and <tt>destroy</tt> are the same: they
    # cause the records in the join table to be removed.
    #
    # For +has_many+, <tt>destroy</tt> will always call the <tt>destroy</tt> method of the
    # record(s) being removed so that callbacks are run. However <tt>delete</tt> will either
    # do the deletion according to the strategy specified by the <tt>:dependent</tt> option, or
    # if no <tt>:dependent</tt> option is given, then it will follow the default strategy.
    # The default strategy is <tt>:nullify</tt> (set the foreign keys to <tt>nil</tt>), except for
    # +has_many+ <tt>:through</tt>, where the default strategy is <tt>delete_all</tt> (delete
    # the join records, without running their callbacks).
    #
    # There is also a <tt>clear</tt> method which is the same as <tt>delete_all</tt>, except that
    # it returns the association rather than the records which have been deleted.
    #
    # === What gets deleted?
    #
    # There is a potential pitfall here: +has_and_belongs_to_many+ and +has_many+ <tt>:through</tt>
    # associations have records in join tables, as well as the associated records. So when we
    # call one of these deletion methods, what exactly should be deleted?
    #
    # The answer is that it is assumed that deletion on an association is about removing the
    # <i>link</i> between the owner and the associated object(s), rather than necessarily the
    # associated objects themselves. So with +has_and_belongs_to_many+ and +has_many+
    # <tt>:through</tt>, the join records will be deleted, but the associated records won't.
    #
    # This makes sense if you think about it: if you were to call <tt>post.tags.delete(Tag.find_by_name('food'))</tt>
    # you would want the 'food' tag to be unlinked from the post, rather than for the tag itself
    # to be removed from the database.
    #
    # However, there are examples where this strategy doesn't make sense. For example, suppose
    # a person has many projects, and each project has many tasks. If we deleted one of a person's
    # tasks, we would probably not want the project to be deleted. In this scenario, the delete method
    # won't actually work: it can only be used if the association on the join model is a
    # +belongs_to+. In other situations you are expected to perform operations directly on
    # either the associated records or the <tt>:through</tt> association.
    #
    # With a regular +has_many+ there is no distinction between the "associated records"
    # and the "link", so there is only one choice for what gets deleted.
    #
    # With +has_and_belongs_to_many+ and +has_many+ <tt>:through</tt>, if you want to delete the
    # associated records themselves, you can always do something along the lines of
    # <tt>person.tasks.each(&:destroy)</tt>.
    #
971
    # == Type safety with <tt>ActiveRecord::AssociationTypeMismatch</tt>
D
Initial  
David Heinemeier Hansson 已提交
972
    #
973
    # If you attempt to assign an object to an association that doesn't match the inferred
974
    # or specified <tt>:class_name</tt>, you'll get an <tt>ActiveRecord::AssociationTypeMismatch</tt>.
D
Initial  
David Heinemeier Hansson 已提交
975 976 977
    #
    # == Options
    #
978
    # All of the association macros can be specialized through options. This makes cases
979
    # more complex than the simple and guessable ones possible.
D
Initial  
David Heinemeier Hansson 已提交
980
    module ClassMethods
P
Pratik Naik 已提交
981 982 983 984 985
      # Specifies a one-to-many association. The following methods for retrieval and query of
      # collections of associated objects will be added:
      #
      # [collection(force_reload = false)]
      #   Returns an array of all the associated objects.
D
Initial  
David Heinemeier Hansson 已提交
986
      #   An empty array is returned if none are found.
P
Pratik Naik 已提交
987 988
      # [collection<<(object, ...)]
      #   Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
989
      #   Note that this operation instantly fires update sql without waiting for the save or update call on the
990
      #   parent object.
P
Pratik Naik 已提交
991 992
      # [collection.delete(object, ...)]
      #   Removes one or more objects from the collection by setting their foreign keys to +NULL+.
993 994
      #   Objects will be in addition destroyed if they're associated with <tt>:dependent => :destroy</tt>,
      #   and deleted if they're associated with <tt>:dependent => :delete_all</tt>.
995 996 997 998
      #
      #   If the <tt>:through</tt> option is used, then the join records are deleted (rather than
      #   nullified) by default, but you can specify <tt>:dependent => :destroy</tt> or
      #   <tt>:dependent => :nullify</tt> to override this.
P
Pratik Naik 已提交
999
      # [collection=objects]
1000 1001 1002
      #   Replaces the collections content by deleting and adding objects as appropriate. If the <tt>:through</tt>
      #   option is true callbacks in the join models are triggered except destroy callbacks, since deletion is
      #   direct.
P
Pratik Naik 已提交
1003 1004 1005
      # [collection_singular_ids]
      #   Returns an array of the associated objects' ids
      # [collection_singular_ids=ids]
1006 1007
      #   Replace the collection with the objects identified by the primary keys in +ids+. This
      #   method loads the models and calls <tt>collection=</tt>. See above.
P
Pratik Naik 已提交
1008 1009 1010 1011
      # [collection.clear]
      #   Removes every object from the collection. This destroys the associated objects if they
      #   are associated with <tt>:dependent => :destroy</tt>, deletes them directly from the
      #   database if <tt>:dependent => :delete_all</tt>, otherwise sets their foreign keys to +NULL+.
1012 1013
      #   If the <tt>:through</tt> option is true no destroy callbacks are invoked on the join models.
      #   Join models are directly deleted.
P
Pratik Naik 已提交
1014 1015 1016 1017 1018 1019
      # [collection.empty?]
      #   Returns +true+ if there are no associated objects.
      # [collection.size]
      #   Returns the number of associated objects.
      # [collection.find(...)]
      #   Finds an associated object according to the same rules as ActiveRecord::Base.find.
P
Pratik Naik 已提交
1020
      # [collection.exists?(...)]
P
Pratik Naik 已提交
1021 1022 1023 1024 1025
      #   Checks whether an associated object with the given conditions exists.
      #   Uses the same rules as ActiveRecord::Base.exists?.
      # [collection.build(attributes = {}, ...)]
      #   Returns one or more new objects of the collection type that have been instantiated
      #   with +attributes+ and linked to this object through a foreign key, but have not yet
P
Pratik Naik 已提交
1026
      #   been saved.
P
Pratik Naik 已提交
1027 1028 1029
      # [collection.create(attributes = {})]
      #   Returns a new object of the collection type that has been instantiated
      #   with +attributes+, linked to this object through a foreign key, and that has already
P
Pratik Naik 已提交
1030 1031
      #   been saved (if it passed the validation). *Note*: This only works if the base model
      #   already exists in the DB, not if it is a new (unsaved) record!
P
Pratik Naik 已提交
1032 1033 1034 1035 1036
      #
      # (*Note*: +collection+ is replaced with the symbol passed as the first argument, so
      # <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.)
      #
      # === Example
D
Initial  
David Heinemeier Hansson 已提交
1037
      #
P
Pratik Naik 已提交
1038 1039
      # Example: A Firm class declares <tt>has_many :clients</tt>, which will add:
      # * <tt>Firm#clients</tt> (similar to <tt>Clients.find :all, :conditions => ["firm_id = ?", id]</tt>)
D
Initial  
David Heinemeier Hansson 已提交
1040 1041
      # * <tt>Firm#clients<<</tt>
      # * <tt>Firm#clients.delete</tt>
1042
      # * <tt>Firm#clients=</tt>
1043
      # * <tt>Firm#client_ids</tt>
1044
      # * <tt>Firm#client_ids=</tt>
D
Initial  
David Heinemeier Hansson 已提交
1045 1046 1047
      # * <tt>Firm#clients.clear</tt>
      # * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>)
      # * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>)
1048
      # * <tt>Firm#clients.find</tt> (similar to <tt>Client.find(id, :conditions => "firm_id = #{id}")</tt>)
P
Pratik Naik 已提交
1049
      # * <tt>Firm#clients.exists?(:name => 'ACME')</tt> (similar to <tt>Client.exists?(:name => 'ACME', :firm_id => firm.id)</tt>)
D
Initial  
David Heinemeier Hansson 已提交
1050
      # * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>)
D
David Heinemeier Hansson 已提交
1051
      # * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>)
D
Initial  
David Heinemeier Hansson 已提交
1052
      # The declaration can also include an options hash to specialize the behavior of the association.
1053
      #
1054
      # === Options
P
Pratik Naik 已提交
1055 1056
      # [:class_name]
      #   Specify the class name of the association. Use it only if that name can't be inferred
1057 1058
      #   from the association name. So <tt>has_many :products</tt> will by default be linked
      #   to the Product class, but if the real class name is SpecialProduct, you'll have to
1059
      #   specify it with this option.
P
Pratik Naik 已提交
1060 1061
      # [:conditions]
      #   Specify the conditions that the associated objects must meet in order to be included as a +WHERE+
1062 1063 1064
      #   SQL fragment, such as <tt>price > 5 AND name LIKE 'B%'</tt>.  Record creations from
      #   the association are scoped if a hash is used.
      #   <tt>has_many :posts, :conditions => {:published => true}</tt> will create published
1065
      #   posts with <tt>@blog.posts.create</tt> or <tt>@blog.posts.build</tt>.
P
Pratik Naik 已提交
1066 1067
      # [:order]
      #   Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
P
Pratik Naik 已提交
1068
      #   such as <tt>last_name, first_name DESC</tt>.
P
Pratik Naik 已提交
1069 1070
      # [:foreign_key]
      #   Specify the foreign key used for the association. By default this is guessed to be the name
1071
      #   of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_many+
1072
      #   association will use "person_id" as the default <tt>:foreign_key</tt>.
P
Pratik Naik 已提交
1073 1074 1075 1076
      # [:primary_key]
      #   Specify the method that returns the primary key used for the association. By default this is +id+.
      # [:dependent]
      #   If set to <tt>:destroy</tt> all the associated objects are destroyed
P
Pratik Naik 已提交
1077 1078
      #   alongside this object by calling their +destroy+ method.  If set to <tt>:delete_all</tt> all associated
      #   objects are deleted *without* calling their +destroy+ method.  If set to <tt>:nullify</tt> all associated
1079 1080 1081
      #   objects' foreign keys are set to +NULL+ *without* calling their +save+ callbacks. If set to
      #   <tt>:restrict</tt> this object cannot be deleted if it has any associated object.
      #
1082 1083 1084
      #   If using with the <tt>:through</tt> option, the association on the join model must be
      #   a +belongs_to+, and the records which get deleted are the join records, rather than
      #   the associated records.
1085
      #
P
Pratik Naik 已提交
1086 1087
      # [:finder_sql]
      #   Specify a complete SQL statement to fetch the association. This is a good way to go for complex
1088
      #   associations that depend on multiple tables. Note: When this option is used, +find_in_collection+
1089
      #   is _not_ added.
P
Pratik Naik 已提交
1090 1091
      # [:counter_sql]
      #   Specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is
1092
      #   specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by
1093
      #   replacing <tt>SELECT ... FROM</tt> with <tt>SELECT COUNT(*) FROM</tt>.
P
Pratik Naik 已提交
1094 1095 1096 1097 1098 1099
      # [:extend]
      #   Specify a named module for extending the proxy. See "Association extensions".
      # [:include]
      #   Specify second-order associations that should be eager loaded when the collection is loaded.
      # [:group]
      #   An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
1100
      # [:having]
1101
      #   Combined with +:group+ this can be used to filter the records that a <tt>GROUP BY</tt>
1102
      #   returns. Uses the <tt>HAVING</tt> SQL-clause.
P
Pratik Naik 已提交
1103 1104 1105
      # [:limit]
      #   An integer determining the limit on the number of rows that should be returned.
      # [:offset]
1106
      #   An integer determining the offset from where the rows should be fetched. So at 5,
1107
      #   it would skip the first 4 rows.
P
Pratik Naik 已提交
1108
      # [:select]
1109 1110
      #   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 but not include the joined columns. Do not forget
1111
      #   to include the primary and foreign keys, otherwise it will raise an error.
P
Pratik Naik 已提交
1112 1113 1114
      # [:as]
      #   Specifies a polymorphic interface (See <tt>belongs_to</tt>).
      # [:through]
1115 1116
      #   Specifies an association through which to perform the query. This can be any other type
      #   of association, including other <tt>:through</tt> associations. Options for <tt>:class_name</tt>,
1117
      #   <tt>:primary_key</tt> and <tt>:foreign_key</tt> are ignored, as the association uses the
1118
      #   source reflection.
1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129
      #
      #   If the association on the join model is a +belongs_to+, the collection can be modified
      #   and the records on the <tt>:through</tt> model will be automatically created and removed
      #   as appropriate. Otherwise, the collection is read-only, so you should manipulate the
      #   <tt>:through</tt> association directly.
      #
      #   If you are going to modify the association (rather than just read from it), then it is
      #   a good idea to set the <tt>:inverse_of</tt> option on the source association on the
      #   join model. This allows associated records to be built which will automatically create
      #   the appropriate join model records when they are saved. (See the 'Association Join Models'
      #   section above.)
P
Pratik Naik 已提交
1130
      # [:source]
1131 1132
      #   Specifies the source association name used by <tt>has_many :through</tt> queries.
      #   Only use it if the name cannot be inferred from the association.
1133
      #   <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either <tt>:subscribers</tt> or
P
Pratik Naik 已提交
1134
      #   <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
P
Pratik Naik 已提交
1135 1136
      # [:source_type]
      #   Specifies type of the source association used by <tt>has_many :through</tt> queries where the source
1137
      #   association is a polymorphic +belongs_to+.
P
Pratik Naik 已提交
1138 1139 1140 1141 1142
      # [:uniq]
      #   If true, duplicates will be omitted from the collection. Useful in conjunction with <tt>:through</tt>.
      # [:readonly]
      #   If true, all the associated objects are readonly through the association.
      # [:validate]
1143
      #   If +false+, don't validate the associated objects when saving the parent object. true by default.
1144
      # [:autosave]
1145
      #   If true, always save the associated objects or destroy them if marked for destruction,
1146
      #   when saving the parent object. If false, never save or destroy the associated objects.
1147
      #   By default, only save associated objects that are new records.
P
Pratik Naik 已提交
1148
      # [:inverse_of]
1149 1150
      #   Specifies the name of the <tt>belongs_to</tt> association on the associated object
      #   that is the inverse of this <tt>has_many</tt> association. Does not work in combination
1151
      #   with <tt>:through</tt> or <tt>:as</tt> options.
1152
      #   See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1153
      #
D
Initial  
David Heinemeier Hansson 已提交
1154 1155
      # Option examples:
      #   has_many :comments, :order => "posted_on"
1156
      #   has_many :comments, :include => :author
D
Initial  
David Heinemeier Hansson 已提交
1157
      #   has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name"
1158 1159
      #   has_many :tracks, :order => "position", :dependent => :destroy
      #   has_many :comments, :dependent => :nullify
R
Rick Olson 已提交
1160
      #   has_many :tags, :as => :taggable
1161
      #   has_many :reports, :readonly => true
1162
      #   has_many :subscribers, :through => :subscriptions, :source => :user
D
Initial  
David Heinemeier Hansson 已提交
1163 1164 1165 1166 1167
      #   has_many :subscribers, :class_name => "Person", :finder_sql =>
      #       'SELECT DISTINCT people.* ' +
      #       'FROM people p, post_subscriptions ps ' +
      #       'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' +
      #       'ORDER BY p.first_name'
1168 1169
      def has_many(name, options = {}, &extension)
        Builder::HasMany.build(self, name, options, &extension)
D
Initial  
David Heinemeier Hansson 已提交
1170 1171
      end

P
Pratik Naik 已提交
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
      # Specifies a one-to-one association with another class. This method should only be used
      # if the other class contains the foreign key. If the current class contains the foreign key,
      # then you should use +belongs_to+ instead. See also ActiveRecord::Associations::ClassMethods's overview
      # on when to use has_one and when to use belongs_to.
      #
      # The following methods for retrieval and query of a single associated object will be added:
      #
      # [association(force_reload = false)]
      #   Returns the associated object. +nil+ is returned if none is found.
      # [association=(associate)]
      #   Assigns the associate object, extracts the primary key, sets it as the foreign key,
D
Initial  
David Heinemeier Hansson 已提交
1183
      #   and saves the associate object.
P
Pratik Naik 已提交
1184 1185 1186
      # [build_association(attributes = {})]
      #   Returns a new object of the associated type that has been instantiated
      #   with +attributes+ and linked to this object through a foreign key, but has not
1187
      #   yet been saved.
P
Pratik Naik 已提交
1188 1189 1190 1191
      # [create_association(attributes = {})]
      #   Returns a new object of the associated type that has been instantiated
      #   with +attributes+, linked to this object through a foreign key, and that
      #   has already been saved (if it passed the validation).
1192 1193 1194
      # [create_association!(attributes = {})]
      #   Does the same as <tt>create_association</tt>, but raises <tt>ActiveRecord::RecordInvalid</tt>
      #   if the record is invalid.
P
Pratik Naik 已提交
1195 1196 1197
      #
      # (+association+ is replaced with the symbol passed as the first argument, so
      # <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.)
D
Initial  
David Heinemeier Hansson 已提交
1198
      #
P
Pratik Naik 已提交
1199 1200 1201
      # === Example
      #
      # An Account class declares <tt>has_one :beneficiary</tt>, which will add:
1202
      # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.find(:first, :conditions => "account_id = #{id}")</tt>)
D
Initial  
David Heinemeier Hansson 已提交
1203
      # * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>)
1204 1205
      # * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>)
      # * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>)
1206
      # * <tt>Account#create_beneficiary!</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save!; b</tt>)
1207
      #
P
Pratik Naik 已提交
1208 1209
      # === Options
      #
D
Initial  
David Heinemeier Hansson 已提交
1210
      # The declaration can also include an options hash to specialize the behavior of the association.
1211
      #
D
Initial  
David Heinemeier Hansson 已提交
1212
      # Options are:
P
Pratik Naik 已提交
1213 1214
      # [:class_name]
      #   Specify the class name of the association. Use it only if that name can't be inferred
P
Pratik Naik 已提交
1215 1216
      #   from the association name. So <tt>has_one :manager</tt> will by default be linked to the Manager class, but
      #   if the real class name is Person, you'll have to specify it with this option.
P
Pratik Naik 已提交
1217 1218
      # [:conditions]
      #   Specify the conditions that the associated object must meet in order to be included as a +WHERE+
1219
      #   SQL fragment, such as <tt>rank = 5</tt>. Record creation from the association is scoped if a hash
1220
      #   is used. <tt>has_one :account, :conditions => {:enabled => true}</tt> will create
1221
      #   an enabled account with <tt>@company.create_account</tt> or <tt>@company.build_account</tt>.
P
Pratik Naik 已提交
1222 1223
      # [:order]
      #   Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
P
Pratik Naik 已提交
1224
      #   such as <tt>last_name, first_name DESC</tt>.
P
Pratik Naik 已提交
1225 1226
      # [:dependent]
      #   If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
1227 1228
      #   <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
      #   If set to <tt>:nullify</tt>, the associated object's foreign key is set to +NULL+.
1229
      #   Also, association is assigned.
P
Pratik Naik 已提交
1230 1231
      # [:foreign_key]
      #   Specify the foreign key used for the association. By default this is guessed to be the name
1232
      #   of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association
1233
      #   will use "person_id" as the default <tt>:foreign_key</tt>.
P
Pratik Naik 已提交
1234 1235 1236 1237 1238 1239 1240
      # [:primary_key]
      #   Specify the method that returns the primary key used for the association. By default this is +id+.
      # [:include]
      #   Specify second-order associations that should be eager loaded when this object is loaded.
      # [:as]
      #   Specifies a polymorphic interface (See <tt>belongs_to</tt>).
      # [:select]
1241 1242
      #   By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if, for example,
      #   you want to do a join but not include the joined columns. Do not forget to include the
1243
      #   primary and foreign keys, otherwise it will raise an error.
P
Pratik Naik 已提交
1244
      # [:through]
1245 1246 1247 1248
      #   Specifies a Join Model through which to perform the query.  Options for <tt>:class_name</tt>,
      #   <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
      #   source reflection. You can only use a <tt>:through</tt> query through a <tt>has_one</tt>
      #   or <tt>belongs_to</tt> association on the join model.
P
Pratik Naik 已提交
1249
      # [:source]
1250 1251
      #   Specifies the source association name used by <tt>has_one :through</tt> queries.
      #   Only use it if the name cannot be inferred from the association.
1252
      #   <tt>has_one :favorite, :through => :favorites</tt> will look for a
1253
      #   <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
P
Pratik Naik 已提交
1254 1255
      # [:source_type]
      #   Specifies type of the source association used by <tt>has_one :through</tt> queries where the source
1256
      #   association is a polymorphic +belongs_to+.
P
Pratik Naik 已提交
1257 1258 1259
      # [:readonly]
      #   If true, the associated object is readonly through the association.
      # [:validate]
1260
      #   If +false+, don't validate the associated object when saving the parent object. +false+ by default.
1261
      # [:autosave]
1262
      #   If true, always save the associated object or destroy it if marked for destruction,
1263
      #   when saving the parent object. If false, never save or destroy the associated object.
1264
      #   By default, only save the associated object if it's a new record.
P
Pratik Naik 已提交
1265
      # [:inverse_of]
1266 1267
      #   Specifies the name of the <tt>belongs_to</tt> association on the associated object
      #   that is the inverse of this <tt>has_one</tt> association.  Does not work in combination
1268
      #   with <tt>:through</tt> or <tt>:as</tt> options.
1269
      #   See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1270
      #
D
Initial  
David Heinemeier Hansson 已提交
1271
      # Option examples:
1272
      #   has_one :credit_card, :dependent => :destroy  # destroys the associated credit card
1273
      #   has_one :credit_card, :dependent => :nullify  # updates the associated records foreign
1274
      #                                                 # key value to NULL rather than destroying it
D
Initial  
David Heinemeier Hansson 已提交
1275 1276
      #   has_one :last_comment, :class_name => "Comment", :order => "posted_on"
      #   has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'"
1277
      #   has_one :attachment, :as => :attachable
1278
      #   has_one :boss, :readonly => :true
1279 1280
      #   has_one :club, :through => :membership
      #   has_one :primary_address, :through => :addressables, :conditions => ["addressable.primary = ?", true], :source => :addressable
1281 1282
      def has_one(name, options = {})
        Builder::HasOne.build(self, name, options)
D
Initial  
David Heinemeier Hansson 已提交
1283 1284
      end

P
Pratik Naik 已提交
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298
      # Specifies a one-to-one association with another class. This method should only be used
      # if this class contains the foreign key. If the other class contains the foreign key,
      # then you should use +has_one+ instead. See also ActiveRecord::Associations::ClassMethods's overview
      # on when to use +has_one+ and when to use +belongs_to+.
      #
      # Methods will be added for retrieval and query for a single associated object, for which
      # this object holds an id:
      #
      # [association(force_reload = false)]
      #   Returns the associated object. +nil+ is returned if none is found.
      # [association=(associate)]
      #   Assigns the associate object, extracts the primary key, and sets it as the foreign key.
      # [build_association(attributes = {})]
      #   Returns a new object of the associated type that has been instantiated
1299
      #   with +attributes+ and linked to this object through a foreign key, but has not yet been saved.
P
Pratik Naik 已提交
1300 1301 1302 1303
      # [create_association(attributes = {})]
      #   Returns a new object of the associated type that has been instantiated
      #   with +attributes+, linked to this object through a foreign key, and that
      #   has already been saved (if it passed the validation).
1304 1305 1306
      # [create_association!(attributes = {})]
      #   Does the same as <tt>create_association</tt>, but raises <tt>ActiveRecord::RecordInvalid</tt>
      #   if the record is invalid.
P
Pratik Naik 已提交
1307 1308 1309
      #
      # (+association+ is replaced with the symbol passed as the first argument, so
      # <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>.)
D
Initial  
David Heinemeier Hansson 已提交
1310
      #
P
Pratik Naik 已提交
1311 1312 1313
      # === Example
      #
      # A Post class declares <tt>belongs_to :author</tt>, which will add:
D
Initial  
David Heinemeier Hansson 已提交
1314 1315
      # * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>)
      # * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>)
D
David Heinemeier Hansson 已提交
1316 1317
      # * <tt>Post#build_author</tt> (similar to <tt>post.author = Author.new</tt>)
      # * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
1318
      # * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
D
Initial  
David Heinemeier Hansson 已提交
1319
      # The declaration can also include an options hash to specialize the behavior of the association.
1320
      #
P
Pratik Naik 已提交
1321 1322 1323 1324
      # === Options
      #
      # [:class_name]
      #   Specify the class name of the association. Use it only if that name can't be inferred
P
Pratik Naik 已提交
1325 1326
      #   from the association name. So <tt>has_one :author</tt> will by default be linked to the Author class, but
      #   if the real class name is Person, you'll have to specify it with this option.
P
Pratik Naik 已提交
1327 1328
      # [:conditions]
      #   Specify the conditions that the associated object must meet in order to be included as a +WHERE+
1329
      #   SQL fragment, such as <tt>authorized = 1</tt>.
P
Pratik Naik 已提交
1330
      # [:select]
1331 1332
      #   By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed
      #   if, for example, you want to do a join but not include the joined columns. Do not
1333
      #   forget to include the primary and foreign keys, otherwise it will raise an error.
P
Pratik Naik 已提交
1334 1335
      # [:foreign_key]
      #   Specify the foreign key used for the association. By default this is guessed to be the name
1336 1337 1338
      #   of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt>
      #   association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
      #   <tt>belongs_to :favorite_person, :class_name => "Person"</tt> will use a foreign key
1339
      #   of "favorite_person_id".
1340 1341 1342 1343 1344
      # [:foreign_type]
      #   Specify the column used to store the associated object's type, if this is a polymorphic
      #   association. By default this is guessed to be the name of the association with a "_type"
      #   suffix. So a class that defines a <tt>belongs_to :taggable, :polymorphic => true</tt>
      #   association will use "taggable_type" as the default <tt>:foreign_type</tt>.
1345
      # [:primary_key]
1346
      #   Specify the method that returns the primary key of associated object used for the association.
1347
      #   By default this is id.
P
Pratik Naik 已提交
1348 1349
      # [:dependent]
      #   If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
1350 1351
      #   <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
      #   This option should not be specified when <tt>belongs_to</tt> is used in conjunction with
1352
      #   a <tt>has_many</tt> relationship on another class because of the potential to leave
1353
      #   orphaned records behind.
P
Pratik Naik 已提交
1354 1355
      # [:counter_cache]
      #   Caches the number of belonging objects on the associate class through the use of +increment_counter+
1356 1357
      #   and +decrement_counter+. The counter cache is incremented when an object of this
      #   class is created and decremented when it's destroyed. This requires that a column
1358
      #   named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
1359 1360
      #   is used on the associate class (such as a Post class). You can also specify a custom counter
      #   cache column by providing a column name instead of a +true+/+false+ value to this
1361
      #   option (e.g., <tt>:counter_cache => :my_custom_counter</tt>.)
1362
      #   Note: Specifying a counter cache will add it to that model's list of readonly attributes
1363
      #   using +attr_readonly+.
P
Pratik Naik 已提交
1364 1365 1366 1367
      # [:include]
      #   Specify second-order associations that should be eager loaded when this object is loaded.
      # [:polymorphic]
      #   Specify this association is a polymorphic association by passing +true+.
1368
      #   Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
P
Pratik Naik 已提交
1369
      #   to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
P
Pratik Naik 已提交
1370 1371 1372
      # [:readonly]
      #   If true, the associated object is readonly through the association.
      # [:validate]
1373
      #   If +false+, don't validate the associated objects when saving the parent object. +false+ by default.
1374
      # [:autosave]
1375
      #   If true, always save the associated object or destroy it if marked for destruction, when
1376
      #   saving the parent object.
1377 1378
      #   If false, never save or destroy the associated object.
      #   By default, only save the associated object if it's a new record.
1379
      # [:touch]
1380 1381
      #   If true, the associated object will be touched (the updated_at/on attributes set to now)
      #   when this record is either saved or destroyed. If you specify a symbol, that attribute
1382
      #   will be updated with the current time in addition to the updated_at/on attribute.
P
Pratik Naik 已提交
1383
      # [:inverse_of]
1384 1385
      #   Specifies the name of the <tt>has_one</tt> or <tt>has_many</tt> association on the associated
      #   object that is the inverse of this <tt>belongs_to</tt> association.  Does not work in
1386
      #   combination with the <tt>:polymorphic</tt> options.
1387
      #   See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
D
Initial  
David Heinemeier Hansson 已提交
1388 1389 1390
      #
      # Option examples:
      #   belongs_to :firm, :foreign_key => "client_of"
1391
      #   belongs_to :person, :primary_key => "name", :foreign_key => "person_name"
D
Initial  
David Heinemeier Hansson 已提交
1392
      #   belongs_to :author, :class_name => "Person", :foreign_key => "author_id"
1393
      #   belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id",
D
Initial  
David Heinemeier Hansson 已提交
1394
      #              :conditions => 'discounts > #{payments_count}'
R
Rick Olson 已提交
1395
      #   belongs_to :attachable, :polymorphic => true
1396
      #   belongs_to :project, :readonly => true
1397
      #   belongs_to :post, :counter_cache => true
1398 1399
      #   belongs_to :company, :touch => true
      #   belongs_to :company, :touch => :employees_last_updated_at
1400 1401
      def belongs_to(name, options = {})
        Builder::BelongsTo.build(self, name, options)
1402 1403
      end

P
Pratik Naik 已提交
1404 1405 1406
      # Specifies a many-to-many relationship with another class. This associates two classes via an
      # intermediate join table.  Unless the join table is explicitly specified as an option, it is
      # guessed using the lexical order of the class names. So a join between Developer and Project
1407 1408 1409
      # will give the default join table name of "developers_projects" because "D" outranks "P".
      # Note that this precedence is calculated using the <tt><</tt> operator for String.  This
      # means that if the strings are of different lengths, and the strings are equal when compared
1410
      # up to the shortest length, then the longer string is considered of higher
P
Pratik Naik 已提交
1411 1412 1413 1414
      # lexical precedence than the shorter one.  For example, one would expect the tables "paper_boxes" and "papers"
      # to generate a join table name of "papers_paper_boxes" because of the length of the name "paper_boxes",
      # but it in fact generates a join table name of "paper_boxes_papers".  Be aware of this caveat, and use the
      # custom <tt>:join_table</tt> option if you need to.
D
Initial  
David Heinemeier Hansson 已提交
1415
      #
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431
      # The join table should not have a primary key or a model associated with it. You must manually generate the
      # join table with a migration such as this:
      #
      #   class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration
      #     def self.up
      #       create_table :developers_projects, :id => false do |t|
      #         t.integer :developer_id
      #         t.integer :project_id
      #       end
      #     end
      #
      #     def self.down
      #       drop_table :developers_projects
      #     end
      #   end
      #
1432
      # Adds the following methods for retrieval and query:
P
Pratik Naik 已提交
1433 1434 1435
      #
      # [collection(force_reload = false)]
      #   Returns an array of all the associated objects.
1436
      #   An empty array is returned if none are found.
P
Pratik Naik 已提交
1437 1438
      # [collection<<(object, ...)]
      #   Adds one or more objects to the collection by creating associations in the join table
1439
      #   (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
1440
      #   Note that this operation instantly fires update sql without waiting for the save or update call on the
1441
      #   parent object.
P
Pratik Naik 已提交
1442 1443
      # [collection.delete(object, ...)]
      #   Removes one or more objects from the collection by removing their associations from the join table.
D
Initial  
David Heinemeier Hansson 已提交
1444
      #   This does not destroy the objects.
P
Pratik Naik 已提交
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458
      # [collection=objects]
      #   Replaces the collection's content by deleting and adding objects as appropriate.
      # [collection_singular_ids]
      #   Returns an array of the associated objects' ids.
      # [collection_singular_ids=ids]
      #   Replace the collection by the objects identified by the primary keys in +ids+.
      # [collection.clear]
      #   Removes every object from the collection. This does not destroy the objects.
      # [collection.empty?]
      #   Returns +true+ if there are no associated objects.
      # [collection.size]
      #   Returns the number of associated objects.
      # [collection.find(id)]
      #   Finds an associated object responding to the +id+ and that
1459
      #   meets the condition that it has to be associated with this object.
P
Pratik Naik 已提交
1460
      #   Uses the same rules as ActiveRecord::Base.find.
P
Pratik Naik 已提交
1461
      # [collection.exists?(...)]
P
Pratik Naik 已提交
1462 1463 1464 1465
      #   Checks whether an associated object with the given conditions exists.
      #   Uses the same rules as ActiveRecord::Base.exists?.
      # [collection.build(attributes = {})]
      #   Returns a new object of the collection type that has been instantiated
1466
      #   with +attributes+ and linked to this object through the join table, but has not yet been saved.
P
Pratik Naik 已提交
1467 1468
      # [collection.create(attributes = {})]
      #   Returns a new object of the collection type that has been instantiated
1469
      #   with +attributes+, linked to this object through the join table, and that has already been
1470
      #   saved (if it passed the validation).
D
Initial  
David Heinemeier Hansson 已提交
1471
      #
P
Pratik Naik 已提交
1472 1473 1474 1475 1476 1477
      # (+collection+ is replaced with the symbol passed as the first argument, so
      # <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.)
      #
      # === Example
      #
      # A Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add:
D
Initial  
David Heinemeier Hansson 已提交
1478 1479 1480
      # * <tt>Developer#projects</tt>
      # * <tt>Developer#projects<<</tt>
      # * <tt>Developer#projects.delete</tt>
1481
      # * <tt>Developer#projects=</tt>
1482
      # * <tt>Developer#project_ids</tt>
1483
      # * <tt>Developer#project_ids=</tt>
D
Initial  
David Heinemeier Hansson 已提交
1484 1485 1486 1487
      # * <tt>Developer#projects.clear</tt>
      # * <tt>Developer#projects.empty?</tt>
      # * <tt>Developer#projects.size</tt>
      # * <tt>Developer#projects.find(id)</tt>
1488
      # * <tt>Developer#projects.exists?(...)</tt>
1489 1490
      # * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("project_id" => id)</tt>)
      # * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("project_id" => id); c.save; c</tt>)
D
Initial  
David Heinemeier Hansson 已提交
1491
      # The declaration may include an options hash to specialize the behavior of the association.
1492
      #
P
Pratik Naik 已提交
1493 1494 1495 1496
      # === Options
      #
      # [:class_name]
      #   Specify the class name of the association. Use it only if that name can't be inferred
1497
      #   from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the
P
Pratik Naik 已提交
1498
      #   Project class, but if the real class name is SuperProject, you'll have to specify it with this option.
P
Pratik Naik 已提交
1499 1500 1501 1502 1503 1504
      # [:join_table]
      #   Specify the name of the join table if the default based on lexical order isn't what you want.
      #   <b>WARNING:</b> If you're overwriting the table name of either class, the +table_name+ method
      #   MUST be declared underneath any +has_and_belongs_to_many+ declaration in order to work.
      # [:foreign_key]
      #   Specify the foreign key used for the association. By default this is guessed to be the name
1505 1506
      #   of this class in lower-case and "_id" suffixed. So a Person class that makes
      #   a +has_and_belongs_to_many+ association to Project will use "person_id" as the
1507
      #   default <tt>:foreign_key</tt>.
P
Pratik Naik 已提交
1508
      # [:association_foreign_key]
P
Pratik Naik 已提交
1509 1510 1511 1512
      #   Specify the foreign key used for the association on the receiving side of the association.
      #   By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
      #   So if a Person class makes a +has_and_belongs_to_many+ association to Project,
      #   the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
P
Pratik Naik 已提交
1513 1514
      # [:conditions]
      #   Specify the conditions that the associated object must meet in order to be included as a +WHERE+
1515
      #   SQL fragment, such as <tt>authorized = 1</tt>.  Record creations from the association are
1516
      #   scoped if a hash is used.
1517
      #   <tt>has_many :posts, :conditions => {:published => true}</tt> will create published posts with <tt>@blog.posts.create</tt>
1518
      #   or <tt>@blog.posts.build</tt>.
P
Pratik Naik 已提交
1519 1520
      # [:order]
      #   Specify the order in which the associated objects are returned as an <tt>ORDER BY</tt> SQL fragment,
1521
      #   such as <tt>last_name, first_name DESC</tt>
P
Pratik Naik 已提交
1522 1523 1524 1525
      # [:uniq]
      #   If true, duplicate associated objects will be ignored by accessors and query methods.
      # [:finder_sql]
      #   Overwrite the default generated SQL statement used to fetch the association with a manual statement
1526 1527
      # [:counter_sql]
      #   Specify a complete SQL statement to fetch the size of the association. If <tt>:finder_sql</tt> is
1528
      #   specified but not <tt>:counter_sql</tt>, <tt>:counter_sql</tt> will be generated by
1529
      #   replacing <tt>SELECT ... FROM</tt> with <tt>SELECT COUNT(*) FROM</tt>.
P
Pratik Naik 已提交
1530 1531
      # [:delete_sql]
      #   Overwrite the default generated SQL statement used to remove links between the associated
P
Pratik Naik 已提交
1532
      #   classes with a manual statement.
P
Pratik Naik 已提交
1533 1534
      # [:insert_sql]
      #   Overwrite the default generated SQL statement used to add links between the associated classes
P
Pratik Naik 已提交
1535
      #   with a manual statement.
P
Pratik Naik 已提交
1536 1537 1538 1539 1540 1541
      # [:extend]
      #   Anonymous module for extending the proxy, see "Association extensions".
      # [:include]
      #   Specify second-order associations that should be eager loaded when the collection is loaded.
      # [:group]
      #   An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
1542
      # [:having]
1543
      #   Combined with +:group+ this can be used to filter the records that a <tt>GROUP BY</tt> returns.
1544
      #   Uses the <tt>HAVING</tt> SQL-clause.
P
Pratik Naik 已提交
1545 1546 1547
      # [:limit]
      #   An integer determining the limit on the number of rows that should be returned.
      # [:offset]
1548
      #   An integer determining the offset from where the rows should be fetched. So at 5,
1549
      #   it would skip the first 4 rows.
P
Pratik Naik 已提交
1550
      # [:select]
1551 1552
      #   By default, this is <tt>*</tt> as in <tt>SELECT * FROM</tt>, but can be changed if, for example,
      #   you want to do a join but not include the joined columns. Do not forget to include the primary
1553
      #   and foreign keys, otherwise it will raise an error.
P
Pratik Naik 已提交
1554 1555 1556
      # [:readonly]
      #   If true, all the associated objects are readonly through the association.
      # [:validate]
1557
      #   If +false+, don't validate the associated objects when saving the parent object. +true+ by default.
1558
      # [:autosave]
1559
      #   If true, always save the associated objects or destroy them if marked for destruction, when
1560
      #   saving the parent object.
1561 1562
      #   If false, never save or destroy the associated objects.
      #   By default, only save associated objects that are new records.
D
Initial  
David Heinemeier Hansson 已提交
1563 1564 1565
      #
      # Option examples:
      #   has_and_belongs_to_many :projects
1566
      #   has_and_belongs_to_many :projects, :include => [ :milestones, :manager ]
D
Initial  
David Heinemeier Hansson 已提交
1567 1568
      #   has_and_belongs_to_many :nations, :class_name => "Country"
      #   has_and_belongs_to_many :categories, :join_table => "prods_cats"
1569
      #   has_and_belongs_to_many :categories, :readonly => true
1570
      #   has_and_belongs_to_many :active_projects, :join_table => 'developers_projects', :delete_sql =>
1571
      #   'DELETE FROM developers_projects WHERE active=1 AND developer_id = #{id} AND project_id = #{record.id}'
1572 1573
      def has_and_belongs_to_many(name, options = {}, &extension)
        Builder::HasAndBelongsToMany.build(self, name, options, &extension)
D
Initial  
David Heinemeier Hansson 已提交
1574
      end
1575
    end
D
Initial  
David Heinemeier Hansson 已提交
1576
  end
1577
end