views:

58

answers:

3

I have two tables, "contents" and "profiles" that can be commented on and rated. I have looked at using polymorphic associations and have decided against it. If I were to use polymorphic associations, the table "ratings" and "comments" would both have this feature.

Is this possible with a concrete supertable implementation? And if so, how would I do it?

A: 

Try this:


class Commentable < ActiveRecord::Base
  has_many :comments
  has_one :profile, :content
end

class Comment < ActiveRecord::Base
  belongs_to :commentable
end

class Content < ActiveRecord::Base
  belongs_to :commentable
end

class Profile < ActiveRecord::Base
  belongs_to :commentable
end

This enables you to (script/console):


# every time you create a profile, link it to the 
# commentable row associated to this profile instance
cid = Commentable.create().id
p = Profile.create(:name => "Inspector Gadget", 
                   :commentable_id => cid)

# when creating the comment, assign the commentable_id 
# to link it to a Profile comment
Comment.new do |c|
  c.body = "go go gadget"
  c.email = "[email protected]"
  c.commentable_id = p.commentable_id
  c.save!
end

To retreive comments from the database from a profile, use this trick:


# Profile.rb

# instead of doing a has many through, 
# we can just use instance method with custom join.
def comments
  find(self.id, :joins => "JOIN commentables cm ON (profiles.id = cm.id) 
  LEFT OUTER JOIN comments c ON (cm.id = c.commentable_id)")
end

Untested code!

see here for more details and explaination, http://stackoverflow.com/questions/922184/why-can-you-not-have-a-foreign-key-in-a-polymorphic-association

A: 

You're mixing up columns on the join. It should be this:


  find(self.id, :joins => "JOIN commentables cm ON (profiles.commentable_id = cm.id) 
  LEFT OUTER JOIN comments c ON (cm.id = c.commentable_id)")

A: 

Correct me if I'm wrong, but couldn't you just do this in Profiles.rb


def comments
  Comments.find(:all, :conditions => ["commentable_id = ?", self.commentable_id])
end