views:

105

answers:

3

In my app I have the classes User, Video, and Vote. Users and Videos can relate to each other in two different ways: as a one-to-many or as a many-to-many. The former is when a User submits a Video (one user can submit many videos). The latter is when a user votes on a video (users have many videos through votes, and vice versa). Here is my code, which does not work (I think -- I may be doing something wrong in the view). Please help me understand the correct way to structure these associations:

class User < ActiveRecord::Base
  has_many :videos, :as => :submissions
  has_many :votes #have tried it without this
  has_many :videos, :as => :likes,  :through => :votes
end

class Vote < ActiveRecord::Base
  belongs_to :video
  belongs_to :user
end

class Video < ActiveRecord::Base
  belongs_to :user
  has_many :votes #have tried it without this . . . superfluous?
  has_many :users, :as => :voters, :through => :votes
end
+2  A: 

I haven't gone and checked, but it goes something like this:

Instead of

has_many :videos, :as => :likes, :through => :votes

Use

has_many :likes, :class_name => "Video", :through => :votes

Same with the bottom:

has_many :users, :as => :voters, :through => :votes

becomes

has_many :voters, :class_name => "User", :through => :votes

:as is used for polymorphic associations. See this chapter in docs for more info.

hakunin
Jeremy Raines
+1  A: 
class User < ActiveRecord::Base
  has_many :videos # Submitted videos
  has_many :votes
  has_many :voted_videos, :through => :votes # User may vote down a vid, so it's not right to call 'likes'
end

class Vote < ActiveRecord::Base
  belongs_to :video
  belongs_to :user
end

class Video < ActiveRecord::Base
  belongs_to :user
  has_many :votes
  has_many :voters, :through => :votes
end

More details can be found here: http://guides.rubyonrails.org/association_basics.html

Hope it helps =)

Staelen
+1  A: 

Thanks for your help guys, definitely pointed me in the right direction. Here is the working code:

class User < ActiveRecord::Base
  has_many :videos, :as => :submissions
  has_many :votes
  has_many :likes, :source => :video, :through => :votes 
end

class Vote < ActiveRecord::Base
  belongs_to :video
  belongs_to :user
end

class Video < ActiveRecord::Base
  belongs_to :user
  has_many :votes
  has_many :voters, :source => :user, :through => :votes 
end

PS I kept it as :likes because in this app they won't be able to downvote, only upvote.

Jeremy Raines