Reputation: 6673
First, I have a polymorphic association setup because comments can belong to any object(in my case post and articles).
I want to be able to say:
u = user.first
u.comments #This will list all comments from a user
u.comments.where(:commentable_type => "Post")
This above line doesn't work. it generates a sql: SELECT "comments".* FROM "comments" WHERE "comments"."commentable_id" = 1 AND "comments"."commentable_type" = 'User' AND "comments"."commentable_type" = 'Post'
obviously this would return an empty list because a comment can't belong to 2 types. I also want to be able to say:
f = Food.first
f.comments.first.user #give me the user that posted the first comment
Here's my basic model... any tips on changing this?
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Post < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Article < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class User < ActiveRecord::Base
has_many :comments, :as => :commentable
end
Upvotes: 1
Views: 121
Reputation: 846
You should be able to do the following to achieve what you want:
u.comments.map { |cmt| Post.find(cmt.commentable) }
and likewise for Article. This returns an array of posts or articles. It'll give an error if they don't exist, so you'll have to modify it for that.
I don't totally understand your second question. If f.comments.first returns you just one comment, then .user should return you the user for that comment, assuming you have the classes User and Comment set-up correctly (with User has_many comments / Comment belongs_to user, as Alexandre Abreu points out), but maybe I'm misunderstanding your question.
Upvotes: 0
Reputation: 1417
I think you should review your comment model, it should look like:
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :commentable, :polymorphic => true
end
So you'd have two relationships, the first will point to who posted the comment, the other will point to the object being commented.
Comment.first.user # this will return the user
Comment.first.commentable # this will return the object which the comment was attached (Post, Article or ?Food?)
Dont forget the migrations if you wish to try this approach.
Upvotes: 4