Method: ActiveRecord::Associations::ClassMethods#has_many
- Defined in:
- lib/active_record/associations.rb
#has_many(name, scope = nil, **options, &extension) ⇒ Object
Specifies a one-to-many association. The following methods for retrieval and query of collections of associated objects will be added:
collection is a placeholder for the symbol passed as the name argument, so has_many :clients would add among others clients.empty?.
collection-
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 withdependent: :destroy, and deleted if they’re associated withdependent: :delete_all.If the
:throughoption is used, then the join records are deleted (rather than nullified) by default, but you can specifydependent: :destroyordependent: :nullifyto override this. collection.destroy(object, ...)-
Removes one or more objects from the collection by running
destroyon each record, regardless of any dependent option, ensuring callbacks are run.If the
:throughoption is used, then the join records are destroyed instead, not the objects themselves. collection=objects-
Replaces the collections content by deleting and adding objects as appropriate. If the
:throughoption is true callbacks in the join models are triggered except destroy callbacks, since deletion is direct by default. You can specifydependent: :destroyordependent: :nullifyto override this. collection_singular_ids-
Returns an array of the associated objects’ ids
collection_singular_ids=ids-
Replace the collection with the objects identified by the primary keys in
ids. This method loads the models and callscollection=. See above. collection.clear-
Removes every object from the collection. This destroys the associated objects if they are associated with
dependent: :destroy, deletes them directly from the database ifdependent: :delete_all, otherwise sets their foreign keys toNULL. If the:throughoption is true no destroy callbacks are invoked on the join models. Join models are directly deleted. collection.empty?-
Returns
trueif 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::FinderMethods#find.
collection.exists?(...)-
Checks whether an associated object with the given conditions exists. Uses the same rules as ActiveRecord::FinderMethods#exists?.
collection.build(attributes = {}, ...)-
Returns one or more new objects of the collection type that have been instantiated with
attributesand linked to this object through a foreign key, but have not yet been saved. 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 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! collection.create!(attributes = {})-
Does the same as
collection.create, but raises ActiveRecord::RecordInvalid if the record is invalid. collection.reload-
Returns a Relation of all of the associated objects, forcing a database read. An empty Relation is returned if none are found.
Example
class Firm < ActiveRecord::Base
has_many :clients
end
Declaring has_many :clients adds the following methods (and more):
firm = Firm.find(2)
client = Client.find(6)
firm.clients # similar to Client.where(firm_id: 2)
firm.clients << client
firm.clients.delete(client)
firm.clients.destroy(client)
firm.clients = [client]
firm.client_ids
firm.client_ids = [6]
firm.clients.clear
firm.clients.empty? # similar to firm.clients.size == 0
firm.clients.size # similar to Client.count "firm_id = 2"
firm.clients.find # similar to Client.where(firm_id: 2).find(6)
firm.clients.exists?(name: 'ACME') # similar to Client.exists?(name: 'ACME', firm_id: 2)
firm.clients.build # similar to Client.new(firm_id: 2)
firm.clients.create # similar to Client.create(firm_id: 2)
firm.clients.create! # similar to Client.create!(firm_id: 2)
firm.clients.reload
The declaration can also include an options hash to specialize the behavior of the association.
Scopes
You can pass a second argument scope as a callable (i.e. proc or lambda) to retrieve a specific set of records or customize the generated query when you access the associated collection.
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) }
Extensions
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)
end
end
Options
:class_name-
Specify the class name of the association. Use it only if that name can’t be inferred from the association name. So
has_many :productswill by default be linked to theProductclass, but if the real class name isSpecialProduct, you’ll have to specify it with this option. :foreign_key-
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.Setting the
:foreign_keyoption prevents automatic detection of the association’s inverse, so it is generally a good idea to set the:inverse_ofoption as well. :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 polymorphic association specified on “as” option with a “_type” suffix. So a class that defines a
has_many :tags, as: :taggableassociation will use “taggable_type” as the default:foreign_type. :primary_key-
Specify the name of the column to use as the primary key for the association. By default this is
id. :dependent-
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
:dependentbehavior, and the:dependentbehavior may affect other callbacks.-
nildo nothing (default). -
:destroycauses all the associated objects to also be destroyed. -
:destroy_asyncdestroys all the associated objects in a background job. WARNING: Do not use this option if the association is backed by foreign key constraints in your database. The foreign key constraint actions will occur inside the same transaction that deletes its owner. -
:delete_allcauses all the associated objects to be deleted directly from the database (so callbacks will not be executed). -
:nullifycauses the foreign keys to be set toNULL. Polymorphic type will also be nullified on polymorphic associations. Callbacks are not executed. -
:restrict_with_exceptioncauses an ActiveRecord::DeleteRestrictionError exception to be raised if there are any associated records. -
:restrict_with_errorcauses an error to be added to the owner if there are any associated objects.
If using with the
:throughoption, 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: :destroyon a scoped association, only the scoped objects are destroyed. For example, if a Post model defineshas_many :comments, -> { where published: true }, dependent: :destroyanddestroyis 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. -
:counter_cache-
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_cacheon the #belongs_to association. :as-
Specifies a polymorphic interface (See #belongs_to).
:through-
Specifies an association through which to perform the query.
This can be any other type of association, including other
:throughassociations, but it cannot be a polymorphic association. Options for:class_name,:primary_keyand:foreign_keyare ignored, as the association uses the source reflection.If the association on the join model is a #belongs_to, the collection can be modified and the records on the
:throughmodel will be automatically created and removed as appropriate. Otherwise, the collection is read-only, so you should manipulate the:throughassociation directly.If you are going to modify the association (rather than just read from it), then it is a good idea to set the
:inverse_ofoption 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 Association Join Models and Setting Inverses for more detail. :disable_joins-
Specifies whether joins should be skipped for an association. If set to true, two or more queries will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory due to database limitations. This option is only applicable on
has_many :throughassociations ashas_manyalone do not perform a join. :source-
Specifies the source association name used by #has_many
:throughqueries. Only use it if the name cannot be inferred from the association.has_many :subscribers, through: :subscriptionswill look for either:subscribersor:subscriberon Subscription, unless a:sourceis given. :source_type-
Specifies type of the source association used by #has_many
:throughqueries where the source association is a polymorphic #belongs_to. :validate-
When set to
true, validates new objects added to association when saving the parent object.trueby default. If you want to ensure associated objects are revalidated on every update, usevalidates_associated. :autosave-
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_savecallback. Because callbacks are run in the order they are defined, associated objects may need to be explicitly saved in any user-definedbefore_savecallbacks.Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
:autosavetotrue. :inverse_of-
Specifies the name of the #belongs_to association on the associated object that is the inverse of this #has_many association. See Bi-directional associations for more detail.
:extend-
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.
:strict_loading-
When set to
true, enforces strict loading every time the associated record is loaded through this association. :ensuring_owner_was-
Specifies an instance method to be called on the owner. The method must return true in order for the associated records to be deleted in a background job.
:query_constraints-
Serves as a composite foreign key. Defines the list of columns to be used to query the associated object. This is an optional option. By default Rails will attempt to derive the value automatically. When the value is set the Array size must match associated model’s primary key or
query_constraintssize. :index_errors-
Allows differentiation of multiple validation errors from the association records, by including an index in the error attribute name, e.g.
roles[2].level. When set totrue, the index is based on association order, i.e. database order, with yet to be persisted new records placed at the end. When set to:nested_attributes_order, the index is based on the record order received by nested attributes setter, when accepts_nested_attributes_for is used. - :before_add
-
Defines an association callback that gets triggered before an object is added to the association collection.
- :after_add
-
Defines an association callback that gets triggered after an object is added to the association collection.
- :before_remove
-
Defines an association callback that gets triggered before an object is removed from the association collection.
- :after_remove
-
Defines an association callback that gets triggered after an object is removed from the association collection.
:deprecated-
If true, marks the association as deprecated. Usage of deprecated associations is reported. Please, check the class documentation above for details.
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
has_many :subscribers, through: :subscriptions, disable_joins: true
has_many :comments, strict_loading: true
has_many :comments, query_constraints: [:blog_id, :post_id]
has_many :comments, index_errors: :nested_attributes_order
1427 1428 1429 1430 |
# File 'lib/active_record/associations.rb', line 1427 def has_many(name, scope = nil, **, &extension) reflection = Builder::HasMany.build(self, name, scope, , &extension) Reflection.add_reflection(self, name, reflection) end |