1

RoR 的第二周(没有编程背景)。我有一点问题,我正在做一个 Metacritic 类型的网站。到处都会有收视率。我决定 0 到 33 = 红色 34 到 66 = 橙色 67 到 100 = 绿色 看起来像这样

索引(控制器:显示)

 <td><% if show.reviews.count == 0 %>0
    <% elsif show.reviews.average("rating").between?(33, 66) %>
    <table class="orange">
      <tr>
        <td><b><%= number_with_precision(show.reviews.average("rating"), :precision => 0) %></b></td>
     </tr>
    </table>
    <% elsif show.reviews.average("rating").between?(66, 100) %>
    <table class="green">
      <tr>
        <td><%= number_with_precision(show.reviews.average("rating"), :precision => 0) %></td>
      </tr>
    </table>
    <% elsif show.reviews.average("rating").between?(00, 33) %>
    <table class="red">
      <tr>
        <td><%= number_with_precision(show.reviews.average("rating"), :precision => 0) %></td>
      </tr>
    </table>
    <% end %>
  </td>

我的问题是我需要大量重复该代码,请参阅(我才刚刚开始:show(controller show)

<p>
  Note: <% if @ratings == 0 %>0
  <% elsif @ratings.between?(33, 66) %>
  <table class="orange">
    <tr>
      <td><b><%= number_with_precision(@ratings, :precision => 0) %></b></td>
    </tr>
  </table>
  <% elsif @ratings.between?(66, 100) %>
  <table class="green">
    <tr>
      <td><%= number_with_precision(@ratings, :precision => 0) %></td>
    </tr>
  </table>
  <% elsif @ratings.between?(00, 33) %>
  <table class="red">
    <tr>
      <td><%= number_with_precision(@ratings, :precision => 0) %></td>
    </tr>
  </table>
  <% end %>
</p>

有人告诉我这应该是一个模型,但我真的不知道怎么写。有什么帮助吗?

4

3 回答 3

5

首先,您应该在Show模型中添加一个实例方法,用于检索和缓存节目的平均收视率。这可以防止多次查询数据库以获取相同的数据:

def average_rating
  @average_rating ||= self.reviews.average('rating')
end

为 a 返回适当的 css 类的代码Show可以进入帮助程序(例如ShowHelper):

module ShowHelper
  def average_rating_class_for(show)
    if show.average_rating < 34
      'red'
    elsif show.average_rating > 66
      'green'
    else
      'orange'
    end
  end
end

有了这个,你的观点变得更加清晰:

<td>
<% if show.reviews.count == 0 %>
  0
<% else %>
  <table class="<%= average_rating_class_for(show) %>">
    <tr>
      <td><%= number_with_precision(show.average_rating, :precision => 0) %></td>
    </tr>
  </table>
<% end %>
</td>

和:

<p>
  Note:
<% if @show.reviews.count == 0 %>
  0
<% else %>
  <table class="<%= average_rating_class_for(@show) %>">
    <tr>
      <td><%= number_with_precision(@show.average_rating, :precision => 0) %></td>
    </tr>
  </table>
<% end %>
</p>

您甚至可以将整个表的生成移动到模型中。(虽然你不应该在这里使用桌子,但那是另一回事。)

module ShowHelper
  def average_rating_class_for(show)
    if show.average_rating < 34
      'red'
    elsif show.average_rating > 66
      'green'
    else
      'orange'
    end
  end

  def average_rating_table_for(show)
    if show.reviews.count == 0
      '0'
    else
      content_tag :table do
        content_tag :tr do
          contect_tag :td, :class => average_rating_class_for(show) do
            number_with_precision(show.average_rating, :precision => 0)
          end
        end
      end
    end
  end
end

有了这个,你的观点变成:

<td>
  <%= average_rating_table_for(show) %>
</td>

安德烈的建议也是可能的,但对于像你这样的初学者来说可能有点难以理解。这更简单。

于 2012-10-16T04:54:03.437 回答
2

您需要在应用目录中创建一个名为 Presenters 的新文件夹。然后您将要创建一个名为 rating_presenter.rb 的文件

这将是您的演示者文件

class RatingPresenter
  def initialize(rating, template)
    @rating = rating
    @template = template
  end

  def get_ratings
     # here you will house the logic to display your tables as needed
     # I would probably determine the output to return the class to set the table accordingly
     # keep in mind that view helpers are available
     # ie.  h.link_to or h.form_tag
  end

  private
    def h # we don't want to be saying @template.link_to etc everywhere, so this is a shortcut
      @template 
    end
end

而在application_helper.rb文件中我们需要确定类才能呈现类

def present(object, klass = nil)
  klass ||= "#{object.class}Presenter".constantize # assign object or nil
  presenter = klass.new(object, self)  # assign presenter to object instance
  yield presenter if block_given?  # yield if block is given
  presenter # return presenter
end

所以在你看来你调用了那个辅助方法

<% present @rating do |rating_presenter| %>
  <p>
    <%= rating_presenter.get_ratings %>
  </p>
<% end %>

所以这是一个快速而肮脏的例子,来自我学到的几个资源。您将需要尝试/打破一些东西以使其适合您的需求。您可以扩展该get_ratings方法并使用多种方法来构建您的表(这是推荐的),而不是让一种方法负责整个事情。它将帮助您隔离问题。希望这会为您指明正确的方向

您还应该在 google 上搜索“presenters +rails”,您可能会找到更多有助于您理解这个概念的文章。最后,rails 具有处理复杂视图逻辑的 gem,请查看 Draper。 https://github.com/drapergem/draper

于 2012-10-16T04:40:31.313 回答
0

我认为对于使用演示者的“RoR 的第二周(没有编程背景)”的人来说有点超出范围。也应该尝试一步一步地简单化,并且只到一个人熟悉的水平(在使用一个不理解的结构时没有用处)

我的建议是简单地编写一个小助手来决定 div 应该是哪种颜色。作为第一枪,只需将以下方法放入 app/helpers/application_helper.rb

def color_for_rating(rating)
  if show.average_rating < 34
    'red'
  elsif show.average_rating > 66
    'green'
  else
    'orange'
  end
end

然后,您可以使用帮助程序为您的表格类提供正确的颜色,如下清理您的索引视图

 <td><% if show.reviews.count == 0 %>0
    <% else %>
    <table class="<%= color_for_rating(show.reviews.average("rating")) %>" >
      <tr>
        <td><b><%= number_with_precision(show.reviews.average("rating"), :precision => 0) %></b></td>
     </tr>
    </table>
    <% end %>
  </td>

一旦您对这种更简单的方法感到满意并稍微使用了它,您就可以回来查看其他答案中给出的更高级的解决方案。

于 2012-10-16T09:29:55.703 回答