Я часто сталкиваюсь с запахом кода, когда использую метод Enumerable 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)..@through.to_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. Я чувствую, что есть лучший способ получить то, что мне нужно, и уменьшить объем обработки запросов и рубинов.