Passing an object for a polymorphic search parameter in Rails find / where

Say I have:

class Comment < 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 the comments in Jim's photo:

 @jims_photo = Photo.where(:of => "Jim") @photo_comments = Comment.where(:commentable => @jims_photo) 

this doesn't seem to work on rails (Rails 3). The generated request does not seem to extend the polymorphic object into the commentable_id and commentable_type fields:

 SQLite3::SQLException: no such column: comments.commentable: 

I'm new to rubies and rails, so I might have misused the paradigm, but I expected the rails to automatically expand

 :commentable => @jims_photo 

in

 :commentable_id => @jims_photo.id, :commentable_type => @jims_photo.class.name 
+4
source share
2 answers

If you want to be safe:

 :commentable_id => @jims_photo.id, :commentable_type => @jims_photo.class.name 

Then I would recommend replacing .class.name with .base_class (you really don't need name : to_s returns name and will be called automatically).

The reason for this is that when ActiveRecord stores _type for polymorphic association, it will use base_class to ensure that it does not save the class, which itself is polymorphic.

If you play with store_full_sti_class , you may have to take even more precautions.

I highly recommend looking at the RTI Rails code here .

+3
source

The Rails Guide is one of the best, so I suggest you start reading Polymorphic Associations

You class declarations look fine, and I assume you are also migrating. 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 

No, if you have an Article or Photo object and you want to get comments on this object, then the Thilo suggestion will be correct. All you have to do is the following: @jims_photo.comments

If, on the other hand, you have an instance of the Comment model, you can get the parent element as follows: @comment.commentable . But if you want comments on Jim's photos to do the best thing. Otherwise, you need to specify the arguments as :commentable_id and commentable_type . I do not know a single crawler that extends a polymorphic object into the commentable_id and commentable_type fields for you.

But you can always create a class method for this:

 def self.find_by_parent(parent) where(:commentable_id => parent.id, :commentable_type => parent.class.name) end 
+2
source

All Articles