Very Important in belongs to

The belongs_to association supports these options:

  • :autosave
  • :class_name
  • :counter_cache
  • :dependent
  • :foreign_key
  • :primary_key
  • :inverse_of
  • :polymorphic
  • :touch
  • :validate
  • :optional


4.1.2.1 :autosave

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

4.1.2.2 :class_name

If the name of the other model cannot be derived from the association name, you can use the :class_name option to supply the model name. For example, if a book belongs to an author, but the actual name of the model containing authors is Patron, you'd set things up this way:

class Book < ApplicationRecord
  belongs_to :author, class_name: "Patron"
end
4.1.2.3 :counter_cache

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

class Book < ApplicationRecord
  belongs_to :author
end
class Author < ApplicationRecord
  has_many :books
end

With these declarations, asking for the value of @author.books.size requires making a call to the database to perform a COUNT(*) query. To avoid this call, you can add a counter cache to the belonging model:

class Book < ApplicationRecord
  belongs_to :author, counter_cache: true
end
class Author < ApplicationRecord
  has_many :books
end

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

Although the :counter_cache option is specified on the model that includes the belongs_to declaration, the actual column must be added to the associated (has_many) model. In the case above, you would need to add a column named books_count to the Author model.

You can override the default column name by specifying a custom column name in the counter_cache declaration instead of true. For example, to use count_of_books instead of books_count:

class Book < ApplicationRecord
  belongs_to :author, counter_cache: :count_of_books
end
class Author < ApplicationRecord
  has_many :books
end

You only need to specify the :counter_cache option on the belongs_to side of the association.

Counter cache columns are added to the containing model's list of read-only attributes through attr_readonly.

4.1.2.4 :dependent

If you set the :dependent option to:

  • :destroy, when the object is destroyed, destroy will be called on its associated objects.
  • :delete, when the object is destroyed, all its associated objects will be deleted directly from the database without calling their destroy method.

You should not specify this option on a belongs_to association that is connected with a has_many association on the other class. Doing so can lead to orphaned records in your database.

4.1.2.5 :foreign_key

By convention, Rails assumes that the column used to hold the foreign key on this model is the name of the association with the suffix _id added. The :foreign_key option lets you set the name of the foreign key directly:

class Book < ApplicationRecord
  belongs_to :author, class_name: "Patron",
                        foreign_key: "patron_id"
end

In any case, Rails will not create foreign key columns for you. You need to explicitly define them as part of your migrations.

4.1.2.6 :primary_key

By convention, Rails assumes that the id column is used to hold the primary key of its tables. The :primary_key option allows you to specify a different column.

For example, given we have a users table with guid as the primary key. If we want a separate todos table to hold the foreign key user_id in the guid column, then we can use primary_key to achieve this like so:

class User < ApplicationRecord
  self.primary_key = 'guid' # primary key is guid and not id
end
 
class Todo < ApplicationRecord
  belongs_to :user, primary_key: 'guid'
end

When we execute @user.todos.create then the @todo record will have its user_id value as the guid value of @user.

4.1.2.7 :inverse_of

The :inverse_of option specifies the name of the has_many or has_one association that is the inverse of this association.

class Author < ApplicationRecord
  has_many :books, inverse_of: :author
end
 
class Book < ApplicationRecord
  belongs_to :author, inverse_of: :books
end
4.1.2.8 :polymorphic

Passing true to the :polymorphic option indicates that this is a polymorphic association. Polymorphic associations were discussed in detail earlier in this guide.

4.1.2.9 :touch

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

class Book < ApplicationRecord
  belongs_to :author, touch: true
end
 
class Author < ApplicationRecord
  has_many :books
end

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

class Book < ApplicationRecord
  belongs_to :author, touch: :books_updated_at
end
4.1.2.10 :validate

If you set the :validate option to true, then associated objects will be validated whenever you save this object. By default, this is false: associated objects will not be validated when this object is saved.

4.1.2.11 :optional

If you set the :optional option to true, then the presence of the associated object won't be validated. By default, this option is set to false.

4.1.3 Scopes for belongs_to

There may be times when you wish to customize the query used by belongs_to. Such customizations can be achieved via a scope block. For example:

class Book < ApplicationRecord
  belongs_to :author, -> { where active: true }
end

You can use any of the standard querying methods inside the scope block. The following ones are discussed below:

  • where
  • includes
  • readonly
  • select
4.1.3.1 where

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

class Book < ApplicationRecord
  belongs_to :author, -> { where active: true }
end
4.1.3.2 includes

You can use the includes method to specify second-order associations that should be eager-loaded when this association is used. For example, consider these models:

class Chapter < ApplicationRecord
  belongs_to :book
end
 
class Book < ApplicationRecord
  belongs_to :author
  has_many :chapters
end
 
class Author < ApplicationRecord
  has_many :books
end

If you frequently retrieve authors directly from chapters (@chapter.book.author), then you can make your code somewhat more efficient by including authors in the association from chapters to books:

class Chapter < ApplicationRecord
  belongs_to :book, -> { includes :author }
end
 
class Book < ApplicationRecord
  belongs_to :author
  has_many :chapters
end
 
class Author < ApplicationRecord
  has_many :books
end

There's no need to use includes for immediate associations - that is, if you have Book belongs_to :author, then the author is eager-loaded automatically when it's needed.

4.1.3.3 readonly

If you use readonly, then the associated object will be read-only when retrieved via the association.

4.1.3.4 select

The select method lets you override the SQL SELECT clause that is used to retrieve data about the associated object. By default, Rails retrieves all columns.

If you use the select method on a belongs_to association, you should also set the :foreign_key option to guarantee the correct results.

4.1.4 Do Any Associated Objects Exist?

You can see if any associated objects exist by using the association.nil? method:

if @book.author.nil?
  @msg = "No author found for this book"
end
4.1.5 When are Objects Saved?

Assigning an object to a belongs_to association does not automatically save the object. It does not save the associated object either.

 

Comments

Popular posts from this blog

Rails 7 Features :: Comparison with Rails 6 and Rails 5