Blog

Ari
June 19, 2017
Ruby Tutorial No Comments

ActiveRecord Association – Ruby Tutorial

Associations are used to relate ActiveRecord models to each other. And they implement this by having database table and having correct primary and foreign key. The association types that are built  in Ruby On Rails are

  • has_many
  • has_one
  • belongs_to
  • has_and_belongs_to_many
  • has_many, :through

 

The has_many and belongs_to is very popular. It defines the one to many relationship. It is the foundation of which relational databases are created. It has one object which has many other objects. The foreign key in this case contains in the child object. Let’s take an example of this, say we are building a blog application, then the association between blog posts and comments is one to many. That means one blog post object has many comment objects and each comment belongs to the blog post.

The has_one association is used when we have one object that is associated with the only one other object. For example, we are building an application for bank, then a customer has one account. So in such case where one object should be associated to only one other object, we use has_one association.

The has_and_belongs_to_many association is used when we have many to many relationships among our object models. This association is formed by using a join table that keeps track of the association of which object is associated to whom. For example, say we are building a WordPress like content management system and we have categories and posts then we need to assign each post to some categories. So a post can have many categories as well as a category may contain many posts. To model this relationship we create a joint table called pos_categories and keep track of post_id and category_id there.

The next association has_many, :through is used when we need rich join. That means when we need to have much more complexity in our association. That means if we need some additional information that needs to be defined in our join table. Let’s take an example of a online course website like Udemy or Udacity or other. What they do is they have students and courses, the relationship or association between students and courses is many to many but we also need to store the information about when the student enrolled for the course. So based on that date they can process business logic next. For this we need a rich join table called students_course and we need student_id, course_id, enrolled_date in there. So for that reason we need rich association in Rails.

 

Using Queries With Associations

We can also use queries with association. For example we have categories and products then whenever we ask Rails to show products that belong to some category using product.category query we can also use query to get the desired result . For example if we want results that are sorted whenever we ask for products that belong to specific category we can do following

has_many :products, lambda { order(:created_at) }

#Also try the following

has_many :products, lambda { reorder(:created_at) }

#If you want to use where

has_many :products, lambda { where(“price < 10”) }

Now if you run cateogry.products on a category object, you will get the desired output.

 

Destroy Associated Objects

There comes the condition when we have some type of object that is totally dependent on other object. For example, if we have product model, we can have other model called product images. So if we want to delete a product in some case, we also want to delete those images that are associated with that product. Rails has a option for this to define in your model

class Product < ActiveRecord::Base

  has_many :images, :dependent => :destroy

end

 

Now whenever I destroy the products, ActiveRecord will look for the associated record and destroy them at the same time.

 

Touch Associated Objects

It is an ActiveRecord method that we can call on a single object. For example

category = Category.first

category.touch

 

Now what it does it, it tells ActiveRecord to update the updated_at to be the current timestamp. It only works with belongs_to association though. If you want to use this method with some other associations, you will need to write your own custom code.

class Product < ActiveRecord::Base

  has_many :images, :touch => true

end

 

 

Counter Cache

Let’s imagine we have an E-commerce store and we have models products and categories. We have many categories and many products in our database. So what we want to do is we want to display name of categories and number of products associated with that category. What we would do for this problem is use SQL statement like this

SELECT COUNT(*) FROM PRODUCTS WHERE CATEGORY_ID = 1;

 

So if you have more than thousand products in a category than this query inside the loop is going to run thousand times and query the database. That can be a big problem for performance. So we need to use counter caches. Here the parent object’s table stores a count of child objects.

class Category < ActiveRecord::Base

has_many :products

end

 

class Product < ActiveRecord::Base

belongs_to :category, :counter_cache => true

end

 

One thing to remember here is the counter_cache is defined in the belongs_to association side because, we want to update the cache if someone deletes the product. But the actual sorage of this information is stored in parent class or Category class.

 

Build Records On Association

What we used to do create a new products that belong to some category was create a new product object of Product class and assign it into the new catgory by passing the value of category in a hash.Take a look

@product = Product.new(:name => “Rose”, :category => “Flower”)

 

Yes, we can do that but we can also create records directly from the association. Take a look at the following example on how to do so

Flower.Product.build(:name => “Rose”)

So this creates a record on association. Here the build method works the same way as new method. We also have a create method but that saves the record immediately.

 

Conclusion

Now you have power in your hands to create a strong associations between active record objects. If you want to learn about active record association, go here http://guides.rubyonrails.org/association_basics.html

Comment