passing object for polymorphic lookup parameter in Rails find/where
Let's say I have:
class C开发者_StackOverflowomment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Article < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class Photo < ActiveRecord::Base
has_many :comments, :as => :commentable
#...
end
now I want to find all comments on Jim's photo:
@jims_photo = Photo.where(:of => "Jim")
@photo_comments = Comment.where(:commentable => @jims_photo)
this seems to not work in rails (Rails 3). The generated query seems to not expand the polymorphic object into commentable_id and commentable_type fields:
SQLite3::SQLException: no such column: comments.commentable:
I'm new to ruby and rails so I might be using the paradigm incorrectly but my expectation was that rails automatically expands
:commentable => @jims_photo
to:
:commentable_id => @jims_photo.id, :commentable_type => @jims_photo.class.name
If you want to be really safe with:
:commentable_id => @jims_photo.id, :commentable_type => @jims_photo.class.name
Then I'd recommend replacing .class.name
with .base_class
(you don't actually need the name
: to_s
returns name
and will be called automatically).
The reason for this is that when ActiveRecord saves the _type
for a polymorphic association it'll use base_class
to ensure it's not saving a class which itself is a polymorphic one.
If you play with store_full_sti_class
you'll probably have to take even more precautions.
I highly recommend looking at Rails' STI code, here.
The guides for Rails are one of the best so I'd suggest you start reading about Polymorphic Associations
You class declarations looks OK and I'm assuming that you're migrations is as well. But just for the sake of it. Let's say it looks like this:
class CreateComment < ActiveRecord::Migration
def change
create_table :comments do |t|
t.string :name
t.references :commentable, :polymorphic => true
# this is the equivalent of
# t.integer :commentable_id
# t.string :commentable_type
t.timestamps
end
end
end
Not if you have a Article
or Photo
object and you want to get the comments for that object then Thilo's suggestion is right on. All you need to do is this: @jims_photo.comments
If, on the other hand, you have a an instance of the Comment
model, you can get the parent like this: @comment.commentable
. But if you want to get Jim's photo comments best to do it like that. Otherwise, you'd have to supply as arguments both the :commentable_id
and commentable_type
. I'm not aware of any finder that expands the polymorphic object into commentable_id
and commentable_type
fields for you.
But you can always create a class method for that:
def self.find_by_parent(parent)
where(:commentable_id => parent.id, :commentable_type => parent.class.name)
end
精彩评论