我很难决定如何在我的控制器中重构这个方法。这个想法是(在这种情况下)它描绘了过去两周加入(或创建)的用户。
你可能想知道我为什么要做@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)
这样的东西。你们怎么能把它分成我可以在整个应用程序中使用的东西?
答案 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
的方法不起作用,只返回导致整数的记录除了零。