当我使用Enumerable group_by方法时,我经常遇到代码异味。一些旧的代码我重构是一个很好的例子Rails Group_By反模式
def punctuality_report
params[:date] ? @date = Date.strptime(params[:date], "%m/%d/%Y") : @date = Date.today
params[:through] ? @through = Date.strptime(params[:through], "%m/%d/%Y") : @through = @date + 1
time_range = @date.to_formatted_s(:db)[email protected]_formatted_s(:db)
@orders = Order.daily.includes(:store).where('orders.created_at' => time_range).group_by{|o| o.store}
@orders.each_key.each do |s|
eval "@s#{s.id}_early = @orders[s].collect{|o| o if o.early?}.compact"
eval "@s#{s.id}_avg_early = @s#{s.id}_early.count > 0 ? @s#{s.id}_early.collect{|o| o.earliness}.sum/@s#{s.id}_early.count : '0'"
eval "@s#{s.id}_late = @orders[s].collect{|o| o if o.late?}.compact"
eval "@s#{s.id}_avg_late = @s#{s.id}_late.count > 0 ? @s#{s.id}_late.collect{|o| o.lateness}.sum/@s#{s.id}_late.count : '0'"
eval "@s#{s.id}_on_time = @orders[s] - (@s#{s.id}_early | @s#{s.id}_late)"
end
end
好了,所以我通过这个快到了,我清楚地看到,我们需要这份报告重构出单控制器上的动作和入模型的自己清理这个实现逻辑。有一个代码异味,但我仍然与这个orders.group_by散列。
事情是当我在视图层我真的想要散列。我需要从订单中获取摘要,但我需要访问商店。在Activerecord中使用组查询方法只会返回一个关系,这不如可枚举的group_by哈希有用。我觉得有更好的方法来获得我需要的东西,并减少很多这种查询和ruby处理。
我喜欢你对范围的定义,但我担心你错过了'eval'的观点。 – nathanvda 2011-04-29 00:43:53
你是对的...我做到了。你为什么要动态设置实例变量?这意味着您的视图代码具有相同的逻辑,反过来找出设置了哪些实例变量。这也是一个很大的气味。为什么不能定义方法来检索子集(比如所有早期订单),并用这些方法显示它们? – jaredonline 2011-04-29 01:01:08