Как работает готовая загрузка? Я имею в виду, я знаю, что он «делает», но могу ли я воспроизвести его, выполнив «побочный» запрос? - PullRequest
1 голос
/ 03 февраля 2012

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

Обычно для энергичной нагрузки вы говорите:

person.cars.includes(:parts)

Я не очень понимаю, что это делает ... он просто загружает эти другие объекты в память? Связаны ли они с каждым автомобилем в этот момент более существенно, чем просто обмен ключами? Если это просто обмен ключами ... могу ли я загрузить эти «Части» в память и получить к ним доступ, не вызывая явно «включенные»? Например .. что-то вроде:

cars = person.cars
cars_id_array << insert cars ids here
parts = Parts.where(:user_id => person_id, "car_id IN cars_id_array") (just an example)

В этом случае (при условии, что я сделал код записи, который я уверен, что я не сделал .. могу ли я перейти на car1.parts, car2.parts и эти части уже будут загружены в память?

Если нет, то чем занимается загрузка?

1 Ответ

5 голосов
/ 03 февраля 2012

Стремительная загрузка делает что-то очень похожее на то, что вы делаете, но помимо простого запроса к базе данных, оно также устанавливает отношения. Когда вы извлекаете модель из базы данных, у которой есть связанные модели, связанные модели обычно загружаются по требованию. Пример из направляющих :

clients = Client.limit(10)

clients.each do |client|
  puts client.address.postcode
end

Когда вы делаете первый запрос, происходит вызов в базу данных, чтобы получить десять клиентов. Когда вы выполняете их итерацию, чтобы получить почтовый индекс, связанный с адресом клиента (который предположительно находится в другой таблице), вам нужно будет выполнить еще 10 запросов, чтобы получить правильные адреса. Используя активную загрузку, вы можете выполнить все это всего за два запроса (которые обрабатываются под обложками).

clients = Client.includes(:address).limit(10)

Это захватывает десять клиентов, а затем выполняет другой запрос (аналогичный вашему), чтобы получить адреса, которые находятся в массиве client_id. Затем они хранятся в памяти с тактичными отношениями, поэтому вам не нужно делать еще один вызов из базы данных, чтобы получить их.

Если вы попытались повторить это, просто загрузив их отдельно:

clients = Client.limit(10)
addresses = Address.where("client_id in [my ID array]")
clients.each do |client|
  puts client.address.postcode
end

Вы по-прежнему будете использовать базу данных для каждого из адресов, поскольку эти объекты не связаны друг с другом, кроме как через идентификаторы базы данных. Объекты загружены, но отношения между ними не создаются.

...