belongs_to
- 1.0.0 (0)
- 1.1.6 (14)
- 1.2.6 (0)
- 2.0.3 (21)
- 2.1.0 (38)
- 2.2.1 (7)
- 2.3.8 (27)
- 3.0.0 (19)
- 3.0.9 (-9)
- 3.1.0 (27)
- 3.2.1 (0)
- 3.2.8 (0)
- 3.2.13 (0)
- 4.0.2 (-16)
- 4.1.8 (0)
- 4.2.1 (27)
- 4.2.7 (0)
- 4.2.9 (0)
- 5.0.0.1 (23)
- 5.1.7 (13)
- 5.2.3 (3)
- 6.0.0 (3)
- 6.1.3.1 (19)
- 6.1.7.7 (0)
- 7.0.0 (14)
- 7.1.3.2 (35)
- 7.1.3.4 (0)
- What's this?
belongs_to(name, scope = nil, options = {})
public
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 is a placeholder for the symbol passed as the name argument, so belongs_to :author would add among others author.nil?.
- association
-
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 with attributes and linked to this object through a foreign key, but has not yet been saved.
- 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).
- create_association!(attributes = {})
-
Does the same as create_association, but raises ActiveRecord::RecordInvalid if the record is invalid.
- reload_association
-
Returns the associated object, forcing a database read.
Example
A Post class declares belongs_to :author, which will add:
-
Post#author (similar to Author.find(author_id))
-
Post#author=(author) (similar to post.author_id = author.id)
-
Post#build_author (similar to post.author = Author.new)
-
Post#create_author (similar to post.author = Author.new; post.author.save; post.author)
-
Post#create_author! (similar to post.author = Author.new; post.author.save!; post.author)
-
Post#reload_author
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 record or customize the generated query when you access the associated object.
Scope examples:
belongs_to :firm, -> { where(id: 2) } belongs_to :user, -> { joins(:friends) } belongs_to :level, ->(game) { where("game_level > ?", game.current_level) }
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 belongs_to :author 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.
- :foreign_key
-
Specify the foreign key used for the association. By default this is guessed to be the name of the association with an “_id” suffix. So a class that defines a belongs_to :person association will use “person_id” as the default :foreign_key. Similarly, belongs_to :favorite_person, class_name: "Person" will use a foreign key of “favorite_person_id”.
- :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 belongs_to :taggable, polymorphic: true association will use “taggable_type” as the default :foreign_type.
- :primary_key
-
Specify the method that returns the primary key of associated object used for the association. By default this is id.
- :dependent
-
If set to :destroy, the associated object is destroyed when this object is. If set to :delete, the associated object is deleted without calling its destroy method. This option should not be specified when #belongs_to is used in conjunction with a #has_many relationship on another class because of the potential to leave orphaned records behind.
- :counter_cache
-
Caches the number of belonging objects on the associate class through the use of CounterCache::ClassMethods#increment_counter and CounterCache::ClassMethods#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 named #{table_name}_count (such as comments_count for a belonging Comment class) is used on the associate class (such as a Post class) - that is the migration for #{table_name}_count is created on the associate class (such that Post.comments_count will return the count cached, see note below). You can also specify a custom counter cache column by providing a column name instead of a true/false value to this option (e.g., counter_cache: :my_custom_counter.) Note: Specifying a counter cache will add it to that model’s list of readonly attributes using attr_readonly.
- :polymorphic
-
Specify this association is a polymorphic association by passing true. Note: If you’ve enabled the counter cache, then you may want to add the counter cache attribute to the attr_readonly list in the associated classes (e.g. class Post; attr_readonly :comments_count; end).
- :validate
-
When set to true, validates new objects added to association when saving the parent object. false by default. If you want to ensure associated objects are revalidated on every update, use validates_associated.
- :autosave
-
If true, always save the associated object or destroy it if marked for destruction, when saving the parent object. If false, never save or destroy the associated object. By default, only save the associated object if it’s a new record.
Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets :autosave to true.
- :touch
-
If true, the associated object will be touched (the updated_at/on attributes set to current time) when this record is either saved or destroyed. If you specify a symbol, that attribute will be updated with the current time in addition to the updated_at/on attribute. Please note that with touching no validation is performed and only the after_touch, after_commit and after_rollback callbacks are executed.
- :inverse_of
-
Specifies the name of the #has_one or #has_many association on the associated object that is the inverse of this #belongs_to association. Does not work in combination with the :polymorphic options. See ActiveRecord::Associations::ClassMethods’s overview on Bi-directional associations for more detail.
- :optional
-
When set to true, the association will not have its presence validated.
- :required
-
When set to true, the association will also have its presence validated. This will validate the association itself, not the id. You can use :inverse_of to avoid an extra query during validation. NOTE: required is set to true by default and is deprecated. If you don’t want to have association presence validated, use optional: true.
- :default
-
Provide a callable (i.e. proc or lambda) to specify that the association should be initialized with a particular record before validation.
Option examples:
belongs_to :firm, foreign_key: "client_of" belongs_to :person, primary_key: "name", foreign_key: "person_name" belongs_to :author, class_name: "Person", foreign_key: "author_id" belongs_to :valid_coupon, ->(o) { where "discounts > ?", o.payments_count }, class_name: "Coupon", foreign_key: "coupon_id" belongs_to :attachable, polymorphic: true belongs_to :project, -> { readonly } belongs_to :post, counter_cache: true belongs_to :comment, touch: true belongs_to :company, touch: :employees_last_updated_at belongs_to :user, optional: true belongs_to :account, default: -> { company.account }
Undocumented :inverse_of option
Support for the :inverse_of option was backported to 2.3.6+.
Here’s the description from the original commit: http://github.com/rails/rails/commit/ccea98389abbf150b886c9f964b1def47f00f237
You can now add an :inverse_of option to has_one, has_many and belongs_to associations. This is best described with an example:
class Man < ActiveRecord::Base has_one :face, :inverse_of => :man end class Face < ActiveRecord::Base belongs_to :man, :inverse_of => :face end m = Man.first f = m.face
Without :inverse_of m and f.man would be different instances of the same object (f.man being pulled from the database again). With these new :inverse_of options m and f.man are the same in memory instance.
Currently :inverse_of supports has_one and has_many (but not the :through variants) associations. It also supplies inverse support for belongs_to associations where the inverse is a has_one and it’s not a polymorphic.
Can be extended but only with a module
Although not documented, belongs_to does support Association Extensions however it doesn’t accept a block like has_many does. So you can’t do this:
class Account < ActiveRecord::Base belongs_to :person do def do_something_funky # Some exciting code end end end
but you can do this:
module FunkyExtension def do_something_funky # Some exciting code end end class Account < ActiveRecord::Base belongs_to :person, :extend => FunkyExtension end
And then call it like this:
@account = Account.first @account.person.do_something_funky
Extend with an anonymous module
You can extend with an anonymous module for one-off cases that won’t be repeated:
belongs_to :container, :polymorphic => true, :extend => ( Module.new do def find_target ... end end )
The parentheses are important, will fail silently without them.
Easy workaround for missing :through option
Note that belongs_to does not support :through option like has_many (although IMHO it would make sense in some cases), but you can easily simulate it with delegate.
For example:
class Person < ActiveRecord::Base belongs_to :team ... end class Task < ActiveRecord::Base belongs_to :person delegate :team, :to => :person end
There is of course more ways to do it, but this seems to be the easiest to me.
Exension module patch
I’d say its just an oversight.
If you’d like to see all associations get equal support for extension modules take a look at this patch and give it a +1.
Caveat and design hints regarding :counter_cache
(From Obie Fernandez/ The Rails Way, ISBN 978-0321445612. Thanks Obie!)
This caveat:
The value of the counter cache column must be set to zero by default in the database! Otherwise the counter caching won’t work at all. It’s because the way that Rails implements the counter caching behavior is by adding a simple callback that goes directly to the database with an UPDATE command and increments the value of the counter.
And these tips:
If a significant percentage of your association collections will be empty at any given moment, you can optimize performance at the cost of some extra database storage by using counter caches liberally. The reason is that when the counter cache attribute is at zero, Rails won’t even try to query the database for the associated records!
If you’re not careful, and neglect to set a default value of 0 for the counter cache column on the database, or misspell the column name, the counter cache will still seem to work! There is a magic method on all classes with has_many associations called collection_count, just like the counter cache. It will return a correct count value if you don’t have a counter cache option set or the counter cache column value is null!
Patch looks good.
I assume commenting right below the ticket is the “+1” action? :) Thanks for the reply and patch efforts!
:foreign_type option
I’m not sure if this has always been around but in 2.3, belongs_to takes a :foreign_type option on polymorphic associations. This behaves the same way as :foreign_key but for the type field.
missing :through option
So the way to do the equivalent of a has_many :through is to use has_one :through, with the expected names.
so using the other example we could do
eg
class Person < ActiveRecord::Base belongs_to :team ... end class Task < ActiveRecord::Base belongs_to :person has_one :team, :through => :person end
Is :required still valid ?
I get this error when using :required => true
ArgumentError: Unknown key: :required. Valid keys are: :class_name, :class, :foreign_key, :validate, :autosave, :remote, :dependent, :primary_key, :inverse_of, :foreign_type, :polymorphic, :touch, :counter_cache
Is :required not a valid key anymore ?
Can't find documention on :find_by option
I found code that had a :find_by option on belongs_to. I’m sure it’s more or less self explanatory, but I couldn’t find it listed anywhere as an option.
My bad, belongs_to was in a controller, not a model.
Why such inconsistency on 'extend' design?
Thanks for the great note! Finally… it took me quite some time to find this page and track down why there is such inconsistency between belongs_to and, say, has_many, proxy extension design. Do you (or anyone knowledgeable here) know the reason behind such design inconsistency? It’s quite annoying (and quite abstraction- and documentation-defeating) that one has to look this deep into the source code to see what’s going on.… Thanks!
I would just use a validation instead of (the probably removed) :required
Just make sure you validate the presence of the association and not the foreign key, otherwise it will not work on new records.
The down side is that it will require the record in the cache, and will make a query otherwise. You can add `unless: :<foreign_key>?` If that’s a problem for you.
Not a one-to-one-relationship
It’s incorrect to state that belongs_to “Specifies a one-to-one association with another class”.
If the inverse association is has_one then the model specifying belongs_to is the LHS of a zero/one-to-one relationship.
If the inverse association is has_many then the model specifying belongs_to is the LHS of a zero/many-to-one relationship.
Unless you know what the inverse association is, all you can assume is that instances of a class specifying a belongs_to association can be related to at most a single instance of the other class.
Careful when updating foreign key directly
Seems when you change key directly it doesn’t update association automatically.
>> chicken = Chicken.first >> chicken.head => old_head >> chicken.head_id = new_head.id >> chicken.head => old_head
Easy (stupid?) way to fix it:
class Chicken def head_id=(value) self.head = Head.find_by_id(value) end end
:autosave => false vs. :autosave => nil
The documentation above mentions that :autosave => true always saves the association and that it’s “off” by default. What it doesn’t mention what they mean by “off”.
-
:autosave => nil (the default “off” behavior) will still autosave the association if it has changed or is a new record.
-
:autosave => false seems to prevent autosaving of the association, even if it has changed.
I’ve found :autosave => false to be useful behavior when trying to prevent cyclical dependency loops; there are likely other useful use cases out there.