has_many(name, scope = nil, options = {}, &extension) public


collection is a placeholder for the symbol passed as the name argument, so has_many :clients would add among others clients.empty?.

collection(force_reload = false)

Returns a Relation of all the associated objects. An empty Relation is returned if none are found.

collection<<(object, …)

Adds one or more objects to the collection by setting their foreign keys to the collection’s primary key. Note that this operation instantly fires update SQL without waiting for the save or update call on the parent object, unless the parent object is a new record. This will also run validations and callbacks of associated object(s).

collection.delete(object, …)

Removes one or more objects from the collection by setting their foreign keys to NULL. Objects will be in addition destroyed if they’re associated with dependent: :destroy, and deleted if they’re associated with dependent: :delete_all.

If the :through option is used, then the join records are deleted (rather than nullified) by default, but you can specify dependent: :destroy or dependent: :nullify to override this.

collection.destroy(object, …)

Removes one or more objects from the collection by running destroy on each record, regardless of any dependent option, ensuring callbacks are run.

If the :through option is used, then the join records are destroyed instead, not the objects themselves.


Replaces the collections content by deleting and adding objects as appropriate. If the :through option is true callbacks in the join models are triggered except destroy callbacks, since deletion is direct by default. You can specify dependent: :destroy or dependent: :nullify to override this.


Returns an array of the associated objects’ ids




Removes every object from the collection. This destroys the associated objects if they are associated with dependent: :destroy, deletes them directly from the database if dependent: :delete_all, otherwise sets their foreign keys to NULL. If the :through option is true no destroy callbacks are invoked on the join models. Join models are directly deleted.


Returns true if there are no associated objects.


Returns the number of associated objects.


Finds an associated object according to the same rules as ActiveRecord::FinderMethods#find.


Checks whether an associated object with the given conditions exists. Uses the same rules as ActiveRecord::FinderMethods#exists?.

collection.build(attributes = {}, …)


collection.create(attributes = {})


collection.create!(attributes = {})

Does the same as collection.create, but raises ActiveRecord::RecordInvalid if the record is invalid.


Returns a Relation of all of the associated objects, forcing a database read. An empty Relation is returned if none are found.


A Firm class declares has_many :clients, which will add:

  • Firm#clients (similar to Client.where(firm_id: id))

  • Firm#clients<<

  • Firm#clients.delete

  • Firm#clients.destroy

  • Firm#clients=

  • Firm#client_ids

  • Firm#client_ids=

  • Firm#clients.clear



  • Firm#clients.find (similar to Client.where(firm_id: id).find(id))

  • Firm#clients.exists?(name: 'ACME') (similar to Client.exists?(name: 'ACME', firm_id: firm.id))



  • Firm#clients.create! (similar to c = Client.new("firm_id" => id); c.save!)

  • Firm#clients.reload




Scope examples:

has_many :comments, -> { where(author_id: 1) }
has_many :employees, -> { joins(:address) }
has_many :posts, ->(blog) { where("max_post_length > ?", blog.max_post_length) }


The extension argument allows you to pass a block into a has_many association. This is useful for adding new finders, creators and other factory-type methods to be used as part of the association.

Extension examples:

has_many :employees do
  def find_or_create_by_name(name)
    first_name, last_name = name.split(" ", 2)
    find_or_create_by(first_name: first_name, last_name: last_name)





Specify the foreign key used for the association. By default this is guessed to be the name of this class in lower-case and “_id” suffixed. So a Person class that makes a #has_many association will use “person_id” as the default :foreign_key.


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 polymorphic association specified on “as” option with a “_type” suffix. So a class that defines a has_many :tags, as: :taggable association will use “taggable_type” as the default :foreign_type.


Specify the name of the column to use as the primary key for the association. By default this is id.


Controls what happens to the associated objects when their owner is destroyed. Note that these are implemented as callbacks, and Rails executes callbacks in order. Therefore, other similar callbacks may affect the :dependent behavior, and the :dependent behavior may affect other callbacks.

  • :destroy causes all the associated objects to also be destroyed.

  • :delete_all causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).

  • :nullify causes the foreign keys to be set to NULL. Callbacks are not executed.

  • :restrict_with_exception causes an exception to be raised if there are any associated records.

  • :restrict_with_error causes an error to be added to the owner if there are any associated objects.

If using with the :through 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.

If using dependent: :destroy on a scoped association, only the scoped objects are destroyed. For example, if a Post model defines has_many :comments, -> { where published: true }, dependent: :destroy and destroy is called on a post, only published comments are destroyed. This means that any unpublished comments in the database would still contain a foreign key pointing to the now deleted post.


This option can be used to configure a custom named :counter_cache. You only need this option, when you customized the name of your :counter_cache on the #belongs_to association.


Specifies a polymorphic interface (See #belongs_to).



If the association on the join model is a #belongs_to, the collection can be modified and the records on the :through model will be automatically created and removed as appropriate. Otherwise, the collection is read-only, so you should manipulate the :through association directly.



Specifies the source association name used by #has_many :through queries. Only use it if the name cannot be inferred from the association. has_many :subscribers, through: :subscriptions will look for either :subscribers or :subscriber on Subscription, unless a :source is given.


Specifies type of the source association used by #has_many :through queries where the source association is a polymorphic #belongs_to.


When set to true, validates new objects added to association when saving the parent object. true by default. If you want to ensure associated objects are revalidated on every update, use validates_associated.


If true, always save the associated objects or destroy them if marked for destruction, when saving the parent object. If false, never save or destroy the associated objects. By default, only save associated objects that are new records. This option is implemented as a before_save callback. Because callbacks are run in the order they are defined, associated objects may need to be explicitly saved in any user-defined before_save callbacks.

Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets :autosave to true.


Specifies the name of the #belongs_to association on the associated object that is the inverse of this #has_many association. Does not work in combination with :through or :as options. See ActiveRecord::Associations::ClassMethods’s overview on Bi-directional associations for more detail.


Specifies a module or array of modules that will be extended into the association object returned. Useful for defining methods on associations, especially when they should be shared between multiple association objects.

Option examples:

has_many :comments, -> { order("posted_on") }
has_many :comments, -> { includes(:author) }
has_many :people, -> { where(deleted: false).order("name") }, class_name: "Person"
has_many :tracks, -> { order("position") }, dependent: :destroy
has_many :comments, dependent: :nullify
has_many :tags, as: :taggable
has_many :reports, -> { readonly }
has_many :subscribers, through: :subscriptions, source: :user
Show source
Register or log in to add new notes.
March 12, 2009
12 thanks

User a block to extend your associations

You can use blocks to extend your associations with extra methods.

code sample

has_many :children, :dependent => :destroy do
  def at(time)
    proxy_owner.children.find_with_deleted :all, :conditions => [

Model.children.each # do stuff
Model.children.at( 1.week.ago ).each # do old stuff


October 22, 2008
10 thanks

Gotcha when defining :finder_sql or :counter_sql



  SELECT DISTINCT relationships.*
  FROM relationships
  WHERE contact_id = #{id}


August 25, 2010 - (>= v2.3.8)
7 thanks

Undocumented :inverse_of option

Support for the :inverse_of option was backported to 2.3.6+.



class Man < ActiveRecord::Base
  has_one :face, :inverse_of => :man

class Face < ActiveRecord::Base
  belongs_to :man, :inverse_of => :face

m = Man.first
f = m.face



November 5, 2009 - (>= v2.1.0)
7 thanks

Named scope better than conditions


class User


class Post
class User
  has_many :posts



August 17, 2008
6 thanks

Explanation about :dependent option






# product.rb
class Product
  has_many :categorizations
  has_many :categories, :through => :categorizations,
    :before_remove => :fire_before_remove_in_categorizations

  def fire_before_remove_in_categorizations(category)
    categorization = self.categorizations.find_by_category_id(category.id)
    categorization.class.notify_observers(:before_remove, categorization)

# categorization_sweeper.rb
# do not forget to load this sweeper during initialization
class CategorizationSweeper < ActionController::Caching::Sweeper
  observe Categorization

  def before_remove(categorization)
    # expire_cache, expire_fragment, whatever



February 10, 2011 - (<= v2.3.8)
3 thanks

Undocumented callbacks



def set_things(thing)
def remove_things(thing)
October 26, 2010
3 thanks

Polymorphic has_many within inherited class gotcha

Given I have following classes

class User < ActiveRecord::Base

class ::User::Agent < ::User
 has_many :leads,  :as => :creator

I would expect, that running


will result in following query


however it results in


Possible solutions:



class User < ActiveRecord::Base
 self.abstract_class = true

class ::User::Agent < ::User
 has_many :leads,  :as => :creator

 def self.base_class

class User::Agent < ::User
 has_many :leads,
          :as => :creator,
August 17, 2008
1 thank

collection update

in the FirmsController


in the View


<%= f.error_messages %>
<%= f.text_field :name %>
<%@firm.people.each do |person|%>
      <%= pf.text_field :name %>
<%= f.submit "Save" %>


February 23, 2009 - (<= v2.2.1)
1 thank

You can't have many :through with habtm

Imagine the following

a has_many b
b has_and_belongs_to_many c
a has_many c :through => b

a.b works fine

b.c works fine

a.c throws an error!


