當我使用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