2009-11-24 44 views
1

可以说我有一个葡萄酒和啤酒模型/控制器,以及具有许多关系的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会中断,所以我无法将饮料作为局部传递给偏食。

谢谢。

回答

6

你这里有几种不同的选择:

鸭子类型:

在Ruby中,只要一个对象响应的方法调用具有的工作,方法调用。因此,如果啤酒和葡萄酒都有一个属性:名称,那么调用@ result.name可以与任一模型一起使用。

多态关联:

代替具有review.beer或review.wine的。通过多态关联使葡萄酒和啤酒可以被审查。这也可以用于评论,例如,两者都可以评论。请查看acts_as_commentable以了解其工作原理。 Railscasts在这个工作方式上有一个excellent screencast

单表继承:

您可以创建一个对象调用饮料从葡萄酒和啤酒继承。这允许一个地方放置类似的属性,并仍然允许有小的差异。

从您的描述来看,您正在寻找所有三种可能的组合。

+0

我认为用多形性关联来处理这将是这里的首选。 – Ben 2009-11-24 19:52:24

+0

立即检出railscast。看起来这正是我要找的。多谢你们。 – KJF 2009-11-24 19:57:35

1

假设评论没有葡萄酒和啤酒的评论,您可以尝试将其添加到您的评论模型。这可能并不是确切的代码,但重要的是,在你的模型中,你可以找出它是什么类型的评论,你的观点不关心。

def beverage 
    @beverage ||= self.beer || self.wine 
end 
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 

而且BeerWine模式可以是:

class Beer < ActiveRecord::Base 
    has_one :beverage_review, :as => :beverage 
end 

这样,如果您将显示所有评论,您可能会将您的代码编写为:

<% @all_reviews.each do |review| -%> 
    <%= review.review_text -%> 
    <%= review.beverage.name -%> 
<% end -%> 
相关问题