I'm learning rails and trying out polymorphic association. I have listed below a couple of simple models for illustration. Model associations seems to works fine as expected. But what if a user (commenter) would like to leave a comment for a another user? I can't seems to get it to work with these configuration. How do I go about doing so?
class User < ApplicationRecord
# username, email, password_digest
has_many :comments, as: :commentable, dependent: :destroy
end
class Project < ApplicationRecord
# title, completed, user_id
has_many :comments, as: :commentable, dependent: :destroy
end
class Comment < ApplicationRecord
# commenter_id, commentable_type, commentable_id, body
belongs_to :commentable, polymorphic: true
end
in console... setup
user1 = User.frist
user2 = User.last
project = Project.first
pro_comment = project.comments.new(body: 'some text')
pro_comment.commenter_id = user1.id
pro_comment.save
user_comment = user2.comments.new(body: 'some text')
user_comment.commenter_id = user1.id
user_comment.save
expected and actual results
Comment.all => successfully lists pro_comment & user_comment
But...
Comment.find_by(commenter_id: 1) => only listed the pro_comment
(what am I doing wrong?)
Also.. user1.comments => returned an empty object... was expecting 2 objects, as you can see below it's not referencing 'commenter_id' .... result...
comment Load (0.5ms) SELECT "comments".* FROM "comments" WHERE
"comments"."commentable_id" = $1 AND "comments"."commentable_type" = $2
LIMIT $3 [["commentable_id", 1], ["commentable_type", "User"],
["LIMIT", 11]]
=> #<ActiveRecord::Associations::CollectionProxy []>
I also tried ... user1.comments.where(commenter_id: 1) >> which returned...
comment Load (0.4ms) SELECT "comments".* FROM "comments" WHERE
"comments"."commentable_id" = $1 AND "comments"."commentable_type" = $2
AND "comments"."commenter_id" = $3 LIMIT $4 [["commentable_id", 1],
["commentable_type", "User"], ["commenter_id", 1], ["LIMIT", 11]]
=> #<ActiveRecord::AssociationRelation []>
Not sure what I'm doing wrong. Could someone please point me in the right direction. I thank you for your time.
find_by
returns only one record, tryComment.where(commenter_id: 1)
instead.For
user1.comments
being empty, you are mixing the relationships. You should have 2 relationships: comment belongs to a commentable object (a project or a user) and comments also belongs to a commenter (the user you set as commenter_id).It makes sense for
user1.comments
to be empty since the user is the commenter on both comments, it's not the commentable.user2.comments
shouldn't be empty, same forproject.comments
Try something like this:
(check the guide, I may be missing some config option https://guides.rubyonrails.org/v5.2/association_basics.html#has-many-association-reference)
Now you can use
user1.comments_done
anduser1.comments
for comments done by the user and done at the user.