Collapse Content Show 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