2011-07-16 66 views
4

比方說,我有:傳遞對象多態查詢參數的Rails查找/那裏

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 

現在我想找到吉姆的照片所有評論:

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

這似乎是行不通的導軌(導軌3)。生成的查詢似乎無法展開多態對象爲commentable_id和commentable_type領域:

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

我是新來的Ruby和Rails,所以我可能不正確使用的範例,但我的期望是,自動導軌擴展

:commentable => @jims_photo 

到:

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

@ jims_photo.comments不起作用? – Thilo

回答

2

爲Rails的導遊是最好的之一,所以我建議你開始閱讀有關Polymorphic Associations

您的類聲明看起來不錯,我假設您的遷移也是如此。但只是爲了它。比方說,它看起來像這樣:

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 

若你有ArticlePhoto對象,你想獲得該對象的意見,然後蒂洛的建議是正確的。所有你需要做的是這樣的:@jims_photo.comments

如果,另一方面,你有Comment模型的實例,就可以得到父母是這樣的:@comment.commentable。但如果你想讓吉姆的照片評論最好這樣做。否則,您必須提供參數:commentable_idcommentable_type。我不知道有任何查找器將多態對象擴展爲commentable_idcommentable_type字段。

但你總是可以爲創建一個類的方法:

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

如果你想成爲真正的安全與:

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

那麼我建議你用.base_class更換.class.name(你不實際上需要nameto_s返回name並將自動調用)。

原因是當ActiveRecord爲多態關聯保存_type時,它將使用base_class來確保它不保存本身是多態的類。

如果您使用store_full_sti_class,您可能需要採取更多預防措施。

我強烈建議您查看Rails的STI代碼here

+0

什麼是base_class?我得到NoM​​ethodError:未定義的方法'base_class' – fatuhoku

+0

@fatuhoku [see here](http://api.rubyonrails.org/classes/ActiveRecord/Inheritance/ClassMethods.html#method-i-base_class)。 – dukedave