假设我有一个葡萄酒和啤酒模型/控制器以及wine_review和beer_review模型,它们有许多关系。
每个表都有几乎相同的数据类型,例如wine_review和beer_review都有一个评级和评论列。 葡萄酒和啤酒各有名。
如何干掉我的代码,以便他们可以共享相同的视图。
现在我有两种观点做同样的事情,一次是啤酒,一次是葡萄酒。
<% @wine_reviews.each do |review| -%>
<ul>
<li><%= link_to review.wine.name, review.wine %></li>
<li><%= review.rating %></li>
<li><%=h review.comment %></li>
</ul>
<% end -%>
<% @beer_reviews.each do |review| -%>
<ul>
....
....
我真正想做的是像
<li><%= link_to review.beverage.name, review.beverage %></li>
根据我当时所呈现的情况,饮料会被葡萄酒或啤酒取代,但我无法弄清楚如何做到这一点。
我无法将饮料当作局部传递给部分,因为review.beverge会破坏。
感谢。
答案 0 :(得分:6)
您有几种不同的选择:
鸭子打字:
在Ruby中,只要一个对象响应方法调用该方法就可以调用work。因此,如果啤酒和葡萄酒都有一个属性:name,那么调用@ result.name将适用于任何一种模型。
多态关联:
而不是review.beer或review.wine。通过多态关联使葡萄酒和啤酒可审阅。这也适用于评论,例如,两者都可以评论。看看acts_as_commentable是如何工作的。 Railscasts的工作原理excellent screencast。
单表继承:
您可以创建一个名为Beverage的对象,Wine和Beer继承该对象。这允许一个地方放置相似的属性,但仍然允许小的差异。
根据您的描述,您正在考虑这三者的组合。
答案 1 :(得分:1)
假设评论没有葡萄酒和啤酒的评论,您可以尝试将其添加到您的评论模型中。这可能不是确切的代码,但关键是在您的模型中,您会发现它的评论类型和您的观点并不关心。
def beverage
@beverage ||= self.beer || self.wine
end
答案 2 :(得分:1)
多态关联就是答案。您可以设计包含以下内容的评论表:
create_table :beverage_reviews, :force => true do |t|
t.string :review_text
t.integer :rating
t.string :beverage_type
t.string :beverage_id
end
BeverageReview
模型可以是:
class BeverageReview < ActiveRecord::Base
belongs_to :beverage, :polymorphic => true
end
Beer
和Wine
模型可以是:
class Beer < ActiveRecord::Base
has_one :beverage_review, :as => :beverage
end
这样,如果您要显示所有评论,您可以将代码编写为:
<% @all_reviews.each do |review| -%>
<%= review.review_text -%>
<%= review.beverage.name -%>
<% end -%>