Details of the belongs_to relationship in Ruby

A belongs_to relationship creates a one-to-one correspondence with another model. In database terms, this relationship says that this class contains a foreign key. If the foreign key contains another class, has_one should be used instead.

Methods added by belongs_to

When you declare a belongs_to relationship, the declaring class automatically receives five methods related to the relationship:

association

association=(associate)

build_association(attributes = {})

create_association(attributes = {})

create_association!(attributes = {})

reload_association

In all four methods, association is replaced by the character passed as the first argument to belongs_to. For example, we have a declaration:

classBook < ApplicationRecord

  belongs_to :author

end

Each instance of the Book model will have these methods:

author

author=

build_author

create_author

create_author!

reload_author

NOTE: When establishing a new has_one or belongs_to association, you must use the build_ prefix to build the association, as opposed to the association.build method used for has_many or has_and_belongs_to_many associations. To create an association, use the create_ prefix.

association

The association method returns the associated object, if any. If there is no object, returns nil.

@author = @book.author

If the associated object has already been retrieved from the database for that object, the cached version is returned. To override this behavior (and force it to read from the database), call #reload_association on the parent object.

@author = @book.reload_author

association=(associate)

The association= method binds an associated object to that object. In effect, this means extracting the primary key from the related entity and assigning its value to the foreign key.

@book.author = @author

build_association(attributes = {})

The build_association method returns a new object of the associated type. This object will be an instance with the attributes passed in, a relationship will be established with the foreign key of this object, but the associated object will not be saved yet.

@author = @book.build_author(author_number: 123,

                                  author_name: “John Doe”)

create_association(attributes = {})

The create_association method returns a new object of the associated type. This entity will be an instance with the attributes passed in, a relationship will be established with the entity’s foreign key, and if it passes the validations defined in the associated model, the associated entity will be saved.

@author = @book.create_author(author_number: 123,

                                   author_name: “John Doe”)

create_association!(attributes = {})

Works the same as create_association above, but calls ActiveRecord::RecordInvalid if the record is invalid.

(options-for-belongs-to) Options for belongs_to

While Rails uses reasonable defaults that work in many situations, there are times when you want to change the behavior of a belongs_to relationship. This customization is easily done by passing options and scoped blocks when creating a link. For example, this link uses two of these options:

classBook < ApplicationRecord

  belongs_to :author, dependent: :destroy,

    counter_cache: true

end

The belongs_to relationship supports these options:

:autosave

:class_name

:counter_cache

:dependent

:foreign_key

:primary_key

:inverse_of

:polymorphic

:touch

:validate

:optional

:autosave

If you set the :autosave option to true, Rails will save any loaded related members and destroy members marked for destruction whenever the parent object is saved. But setting :autosave to false is not the same as not setting the :autosave option. If the :autosave option is not present, then new related objects will be saved, but updated related objects will not be saved.

:class_name

If the name of another model cannot be derived from the link name, you can use the :class_name option to provide the name of the model. For example, if the book is owned by the author, but the actual name of the model containing the authors is Patron, you can set this as follows:

classBook < ApplicationRecord

  belongs_to :author, class_name: “Patron”

end

:counter_cache

The :counter_cache option can be used to make finding the number of owned objects more efficient. Consider these models:

classBook < ApplicationRecord

  belongs_to :author

end

classAuthor<ApplicationRecord

  has_many:books

end

With these declarations, requesting the @author.books.size value requires a database call to execute the COUNT(*) request. To avoid this, you can add a counter cache to the owned model:

classBook < ApplicationRecord

  belongs_to :author, counter_cache: true

end

classAuthor<ApplicationRecord

  has_many:books

end

With this declaration, Rails will cache the actual value and then return that value in response to the size method.

:polymorphic

Passing true for the :polymorphic option indicates that this is a polymorphic relationship. Polymorphic relationships have been discussed in detail previously.

:touch

If you set the :touch option to true, then the updated_at or updated_on timestamps on the associated object will be set to the current time whenever that object is saved or destroyed:

classBook < ApplicationRecord

  belongs_to :author, touch: true

end

classAuthor<ApplicationRecord

  has_many:books

end

In this case, saving or destroying the book will update the timestamp on the associated author. You can also define a specific timestamp attribute to update:

classBook < ApplicationRecord

  belongs_to :author, touch: :books_updated_at

end

:validate

If you set the :validate option to true, then related objects will be validated whenever you save that object. It defaults to false: related objects are not validated when this object is saved.

:optional

If you set :optional to true, then the presence of related objects will not be validated. The default is set to false.

Scopes for belongs_to

Sometimes you want to customize the query used by belongs_to. Such customization can be achieved with a scope block. For example:

classBook < ApplicationRecord

  belongs_to :author, -> { where active: true },

                        dependent: :destroy

end

Within a scope block, any standard query methods can be used. Next, we will discuss the following ones:

where

includes

readonly

select

where

The where method allows you to specify the conditions that the associated object must meet.

classBook < ApplicationRecord

  belongs_to :author, -> { where active: true }

end

includes

The includes method can be used to define second-order relationships that should be lazily loaded when using this relationship. For example, consider these models:

class LineItem < ApplicationRecord

  belongs_to :book

end

classBook < ApplicationRecord

  belongs_to :author

  has_many :line_items

end

classAuthor<ApplicationRecord

  has_many:books

end

If you often get authors directly from the elements (@line_item.book.author), then you can improve code efficiency by including the authors in the relationship between the book and its elements: NOTE: There is no need to use includes for nearest links – that is, if there is a Book belongs_to :author , the author is automatically lazy loaded when needed.