2013-02-19 80 views
0

我需要將評論鏈接到帖子。然而,Comment可以是(用戶生成的)簡單的文本,(系統生成的)鏈接或(系統生成的)圖像。如何創建多態模型

起初他們都共享相同的屬性。所以我只需要創建一個category屬性,並根據該類別使用text屬性完成不同的事情。

例如:

class Comment < ActiveRecord::Base 
    belongs_to :post 
    belongs_to :author, :class_name => "User" 

    CATEGORY_POST = "post" 
    CATEGORY_IMAGE = "image" 
    CATEGORY_LINK = "link" 

    validates :text, :author, :category, :post, :presence => true 
    validates_inclusion_of :category, :in => [CATEGORY_POST, CATEGORY_IMAGE, CATEGORY_LINK] 

    attr_accessible :author, :text, :category, :post 

    def is_post? 
    self.category == CATEGORY_POST 
    end 

    def is_link? 
    self.category == CATEGORY_LINK 
    end 

    def is_image? 
    self.category == CATEGORY_IMAGE 
    end 

end 

然而,這西港島線不是現在足夠了,因爲我不覺得乾淨傾倒在一個通用的「文本」屬性的每個值。所以我正在考慮創建一個多態模型(如果需要在工廠模式中)。但是當我搜索多態模型時,我得到了一些例子,比如對帖子的評論,但是同一個頁面上的評論,這種關係。我對多態性不同的理解(與在不同範圍內行爲相同的模型相比,在不同情況下行爲不同的模型)?

那麼我將如何建立這種關係?

我在想(和請指正)

Post 
    id 

Comment 
    id 
    post_id 
    category (a enum/string or integer) 
    type_id (references either PostComment, LinkComment or ImageComment based on category) 
    author_id 

PostComment 
    id 
    text 

LinkComment 
    id 
    link 

ImageComment 
    id 
    path 

User (aka Author) 
    id 
    name 

但我不知道如何建立一個模型以便我可以調用post.comments(或author.comments)來獲取所有的意見。一個不錯的將是一個評論的創建將通過評論,而不是鏈接/圖像/ postcomment(註釋充當工廠)

主要問題是,如何設置了ActiveRecord的車型,所以關係保持不變(作者有評論和帖子有評論,評論可以是鏈接,圖片或Postcomment)

回答

1

我只會回答你的主要問題,模型設置。鑑於您在問題中使用的列和表,除了註釋之外,您可以使用以下設置。

# comment.rb 
# change category to category_type 
# change type_id to category_id 
class Comment < ActiveRecord::Base 
    belongs_to :category, polymorphic: true 
    belongs_to :post 
    belongs_to :author, class_name: 'User' 
end 

class PostComment < ActiveRecord::Base 
    has_one :comment, as: :category 
end 

class LinkComment < ActiveRecord::Base 
    has_one :comment, as: :category 
end 

class ImageComment < ActiveRecord::Base 
    has_one :comment, as: :category 
end 

使用該設置,您可以執行以下操作。

>> post = Post.first 
>> comments = post.comments 
>> comments.each do |comment| 
     case comment.category_type 
     when 'ImageComment' 
     puts comment.category.path 
     when 'LinkComment' 
     puts comment.category.link 
     when 'PostComment' 
     puts comment.category.text 
     end 
    end