Rails Relationships


Collapse Content

Here's a brief visual tutorial to Rails relationships or "Associations". See Models and Relationships and Advanced Relationships for detailed tutorials.

has_many & belongs_to

Goal: Each category can have many products, and each product can belong to one category.
Solution: Set up a one-to-many relationship between models.

Database
Add a column for category_id to the products table, to identify the product that a category belongs to.

Migration

rails generate migration AddCategoryIdToProducts category_id:integer

Models

belongs_to - Tell Rails that each product belongs_to a category

class Product < ActiveRecord::Base
  belongs_to :category
end

has_many - Tell Rails that each category has_many products

class Category < ActiveRecord::Base
  has_many :products
end

Code

prod1 = Product.first
prod1.category # returns prod1's category
cat1 = Category.first
cat1.products #returns collection of cat1's products

has_one & belongs_to

Goal: Each user can have one cart, and each cart can belong to one user.
Solution: Set up a one-to-one relationship between models.

Database
Add a column for user_id to the carts table, to identify the user that a cart belongs to.

Migration

rails generate migration AddUserIdToCarts user_id:integer

Models

belongs_to - Tell Rails that each product belongs_to a category

class Cart < ActiveRecord::Base
  belongs_to :user
end

has_one - Tell Rails that each User has_one cart.

class User < ActiveRecord::Base
  has_one :cart
end

Code

user1 = User.first
user.cart # return's user1's cart
cart1 = Cart.first
cart1.user #return's cart1's user

has_many through

Goal: A user should be able to 'like' products. Each user could like many products, and each product could be liked by many users. Easily retrieve the products a user likes.

Solution: Set up a many-to-many relationship between models.

Database
Create a new table likes with 2 columns: user_id and product_id. Each like record stores a relationship between a User and a Product.

Migration - create a Like model and table:

rails generate model Like user_id:integer product_id:integer

Models

Like uses a standard belong_to:

class Like < ActiveRecord::Base
  belongs_to :user
  belongs_to :product
end

Here's a simple has_many through:

class User < ActiveRecord::Base
  has_many :likes
  has_many :products, through: :likes
end

The above code lets you call user.products on a user. Change the name of the relationship and provide a source model:

class User < ActiveRecord::Base
  has_many :likes
  has_many :liked_products, through: :likes, source: :product
end

Now you can call user.liked_products, which is clearer.

The product model uses a standard has_many relationship:

class Product < ActiveRecord::Base
  has_many :likes
end

(It doesn't currently declare a relationship to retrieve 'Liking Users' from a given product.)

Code

prod1 = Product.first
prod1.likes # returns prod1's likes
user1 = User.first
user1.likes #returns user1's likes
user1.liked_products # returns user1's liked products

Additional Relationships

has_and_belongs_to_many

has_many through was covered above. If you know you'll never need to add any columns or methods to the like model, you can skip creating the like model and instead create a has-and-belongs-to-many-association association between users and products. You will still need to create a table to store the relationship.

has_one through

has_one :through is like has_many through for a has_one relationship.

Contact Us
Sign in or email us at [email protected]