Rails включает и нетерпеливую загрузку - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть команда Rails:

Product.includes(:sale, :product_description).select('distinct on (size) *')

Насколько я понимаю, когда я запускаю эту команду, Rails охотно загружает результаты в память, и, поскольку существует только 4 размера, результат должен содержать только 4 записи. Однако, если я сделаю что-то вроде:

result = Product.includes(:sale, :product_description).select('distinct on (size) *')

и затем сделайте: result.size. Результатом будет подсчет всех записей продукта, который равен 435. Но если я сделаю: result.length, тогда я получу ожидаемый ответ, равный 4.

Почему я получаю разные результаты с length и size? Я думал, что при использовании includes все загружается с нетерпением, поэтому length и size должны возвращать одинаковое количество?

Также обратите внимание, что если я сначала запускаю length, а затем size, оба возвращают правильный результат 4. Но если я сначала запускаю size, то я получаю неправильный ответ 435.

1 Ответ

0 голосов
/ 04 сентября 2018

Есть тонкие различия между count, size и length на ActiveRecord::Relations (см. этот ответ о деталях)

В вашем примере length всегда будет выполнять точный запрос, определенный для ActiveRecord::Relation, а затем вызовет length для возвращенного массива.

Принимая во внимание, что result.size будет выполнять запрос count, когда ActiveRecord::Relation не был загружен ранее. Поскольку count возвращает число (а не фактические записи), запрос оптимизируется, а части include и select игнорируются. Это имеет смысл с точки зрения производительности.

Но если Relation уже загружен (например, когда вы вызываете length до size), то size просто вернет размер уже загруженного массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...