在我的控制器中重构一个简单的方法

时间:2010-01-12 05:06:39

标签: ruby-on-rails

我很难决定如何在我的控制器中重构这个方法。这个想法是(在这种情况下)它描绘了过去两周加入(或创建)的用户。

你可能想知道我为什么要做@graph_limit这件事,那是因为我总是希望结果最多的那一天成为条形图上最高的条形图(在视图中只是创建了通过使用css设置<div>的高度来实现css。

基本上我想干掉它......你知道尽可能地改进这个方法:

# Controller
def index

  two_weeks_ago = Date.today - 13.days

  @users_graphed = User.count(:conditions=>["created_at >= ?", two_weeks_ago], :order => 'DATE(created_at) DESC', :group => ["DATE(created_at)"])

  two_weeks_ago.upto(Date.today) do |day|
    @graph_limit = 100/@users_graphed.values.max.to_f
    @users_graphed[day.to_s] ||= 0
  end

end

另外我应该提一下,你们可能会把我的代码撕成碎片......所以我正在为结果做准备。

# View
<% @users_graphed.sort.reverse.each do |user| %>
  <li>       
    <% content_tag :div, :style => "height: #{number_with_precision(user[1] * @graph_limit, :precision => 2)}px; ", :class => "stat_bar" do %>
      <%= content_tag(:span, user[1]) unless user[1] == 0 %>
    <% end %>
  </li>
<% end %>

最终,我的真正目标是将其放入我的应用程序控制器中,并能够按create_at次计算任何模型。也许像tasks.chart_by(2.weeks)这样的东西。你们怎么能把它分成我可以在整个应用程序中使用的东西?

2 个答案:

答案 0 :(得分:3)

我同意Joseph的观点,你的控制器在这里做了很多应该在模型中完成的工作。每当您在控制器中指定多个find参数时,请问自己是否应该在您的模型中。

你在这里进行了大量的迭代,这似乎是不必要的。首先,您不应该在循环内计算@graph_limit。你重新计算了14次,但每次的价值都是一样的。在循环之外做到这一点。

其次,您认为sort.reverse会突出。您已经在查找器中进行了排序(:order => 'DATE(created_at) DESC'),然后您在视图中再次排序,然后将其反转?您应该向数据库询问您希望它们的最终顺序中的值。然后,为了使您的零填充代码工作,您可以反转它,执行Date.today.downto(two_weeks_ago)而不是upto

我会说你应该在SQL中真正做到这一点,但不幸的是(正如你所发现的那样),MySQL很难在不创建日历表的情况下填补缺失的日子。

答案 1 :(得分:0)

感谢乔丹,根据你的想法(顺便说一句,这真的太棒了)我创造了一个这样的帮手:

def graph_by_time(klass, time_ago)
  time_range_start = Date.today - time_ago

  @elements_graphed = klass.count(:conditions=>["created_at >= ?", time_range_start], :order => 'DATE(created_at) DESC', :group => ["DATE(created_at)"])
  @graph_limit = 100/@elements_graphed.values.max.to_f

  time_range_start.upto(Date.today) do |element|
    @elements_graphed[element.to_s] ||= 0
  end

  return @elements_graphed.sort.reverse
end

这里最大的问题是零填充没有与之关联的记录的日期,从upto切换到downto的方法不起作用,只返回导致整数的记录除了零。