开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜