Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modeling Favorites

I'm looking to add a Favorite model to my User and Link models.

Business Logic

  • Users can have multiple links (that is, they can add multiple links)
  • Users can favorite multiple links (of their own or other users)
  • A Link can be favorited by multiple users but have one owner

I'm confused as to how to model this association and how would a user favorite be created once the models are in place?

class User < ActiveRecord::Base
  has_many :links
  has_many :favorites
end

class Link < ActiveRecord::Base
  belongs_to :user
  #can be favorited by multiple users 
end

class Favorite < ActiveRecord::Base
  belongs_to :user
  belongs_to :link 
end
like image 959
Dru Avatar asked Nov 23 '11 02:11

Dru


1 Answers

How about the following data model:

class User < ActiveRecord::Base
  has_many :links
  has_many :favorites, :dependent => :destroy
  has_many :favorite_links, :through => :favorites, :source => :link
end

class Link < ActiveRecord::Base
  belongs_to :user
  has_many   :favorites, :dependent => :destroy
  has_many   :favorited, :through => :favorites, :source => :user
end

class Favorite < ActiveRecord::Base
  belongs_to :user
  belongs_to :link
end

Since User already has an association called links, and Link already has one called users, we cannot use the same name for the has_many :through association (e.g. User has_many :links, :through => :favorites would not work). So, we invent a new association name, and help Rails know what association to load from the intermediary association via the source attribute.

Here's some pseudocode for using this association:

# Some users
user1 = User.create :name => "User1"
user2 = User.create :name => "User2"

# They create some links
link1_1 = user1.links.create :url => "http://link1_1"
link1_2 = user1.links.create :url => "http://link1_2"
link2_1 = user2.links.create :url => "http://link2_1"
link2_2 = user2.links.create :url => "http://link2_2"

# User1 favorites User2's first link
user1.favorites.create :link => link2_1
# User2 favorites both of User1's links
user2.favorites.create :link => link1_1
user2.favorites.create :link => link1_2

user1.links          => [link1_1, link1_2]
user1.favorite_links => [link2_1]
user2.links          => [link2_1, link2_2]
user2.favorite_links => [link1_1, link1_2]
link1_1.favorited    => [user2]

link2_1.destroy

user1.favorite_links => []
user2.links          => [link2_2]
like image 74
Michelle Tilley Avatar answered Sep 28 '22 12:09

Michelle Tilley