Первая проблема заключается в том, что добавление find_by
будет всегда выполнит другой запрос независимо от того, что вы предварительно загрузили (по крайней мере, в Rails 4, хотя я сомневаюсь, что он изменился).Это потому, что find_by
реализован, чтобы генерировать больше SQL.Если вы хотите выполнить предварительную загрузку, вы можете использовать find
вместо этого, что хорошо, если на родительское устройство не существует смешного количества активов, но плохо, если имеется много-много активов, и / или это большие объекты, которыезаняло бы тонну памяти (см. примечание ниже для альтернативного решения).
Вы можете предварительно загрузить ресурсы следующим образом:
parent.children.preload(:parent => :assets) each do |child|
# Will not execute another query
child.parent.assets.find{ |asset| asset.asset_type == "first" }
В качестве альтернативы, вы можете объявить ассоциацию has_many :through
:
class Child < ActiveRecord::Base
belongs_to :parent
has_many :assets, through: :parent
...
end
Тогда вы можете просто
parent.children.preload(:assets).each do |child|
# Will not execute another query
child.assets.find { |asset| asset.asset_type == "first" }
Если вы хотите выполнить поиск в слое db, а не в ruby, вы можете определить ассоциацию с областью действия:
class Parent < ActiveRecord::Base
has_one :first_asset, ->{ where asset_type: "first" }
...
end
Таким образом, вместо этого вы можете preload(:parent => :first_asset)
.