Как «перезагрузить» коллекцию с активной нагрузкой с условиями в рельсах 2.3? - PullRequest
0 голосов
/ 24 февраля 2011

Я поддерживаю старое приложение rails, написанное в 2.3 (думаю, что .5). Есть неэффективный выбор, который приводит к старой проблеме N + 1, которую я пытаюсь исправить.

Во-первых, коллекция Widgets загружается с различными операторами find_by_sql в коммутаторе. После этого следует Widget.association.select, который выполняет N + 1. Я хочу заменить этот цикл выбора энергичной загрузкой виджетов на основе идентификаторов виджетов из find_by_sql. Я понимаю, что мог бы объединить их в 1 запрос, но find_by_sql довольно сложен, поэтому на данный момент я предпринимаю небольшие шаги для оптимизации в 2 запроса.

Так что в основном у меня есть

@widgets = Widget.find_by_sql...

и теперь я хочу использовать @widgets, чтобы сделать что-то вроде

@widgets_and_more = Widget.find(:all, :include => :widget_assoc, :conditions => ["widgets.id IN ", @widgets.ids])

1 Ответ

0 голосов
/ 24 февраля 2011

Вы можете использовать collect или map, чтобы получить массив идентификаторов для использования в IN... части запроса ...

@widgets_and_more = Widget.find(:all, :include => :widget_assoc, :conditions => ["widgets.id IN (?)", @widgets.collect(&:id)])

Или, поскольку Rails будет иметь дело сэто приятно и вызвать .to_param для каждого из объектов, вы можете просто использовать массив @widgets (то есть, если они являются экземпляром Widget и отвечают на .to_param, очевидно) ...

@widgets_and_more = Widget.find(:all, :include => :widget_assoc, :conditions => ["widgets.id IN (?)", @widgets])

Как вы сказали в своем вопросе, связывание двух запросов было бы гораздо более изящным способом справиться с этим.Если вы собираетесь сделать это таким образом, возможно, вы захотите получить первый запрос, чтобы выбрать только идентификаторы, чтобы, по крайней мере, вам не было необходимости хранить две партии одинаковых данных в памяти.

...