Rails 4: найти все записи
Теперь, когда ActiveRecord:: Relation # все устарели в Rails 4, как вы должны перебирать все записи?
Используется для:
Foo.all.each do |foo|
# whatever
end
Я могу приблизить его сейчас так, но он чувствует себя грязным:
Foo.where(true).each do |foo|
# whatever
end
Есть ли лучший способ?
Ответы
Ответ 1
В соответствии с Rails Guide на Active Request Query Interface правильный путь к итерации по всем записям осуществляется с помощью find_each
.
Использование Foo.all.each
будет загружать таблицу целиком в память, создавая экземпляры всех строк; затем перебирать экземпляры. find_each
делает это партиями, что более эффективно с точки зрения использования памяти.
Из руководства:
Метод find_each
извлекает партию записей, а затем выводит каждую запись в блок по отдельности в качестве модели. В следующем примере find_each
будет извлекать 1000 записей (текущий по умолчанию как для find_each
, так и find_in_batches
), а затем каждый отдельный экземпляр каждой записи записывать в блок как модель. Этот процесс повторяется до тех пор, пока все записи не будут обработаны:
User.find_each do |user|
NewsLetter.weekly_deliver(user)
end
Литература:
Ответ 2
да, Foo.all
.
all
устарел на ActiveRecord:: Relation (например, Foo.where(true)
), а не на ActiveRecord:: Base.
http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html#method-i-all
Ответ 3
Примечания к выпуску для Rails 4:
Model.all теперь возвращает ActiveRecord:: Relation, а не массив записей. Используйте Relation # to_a, если вы действительно хотите массив.
Итак, ваш код будет выглядеть так:
Foo.all.to_a.each do |foo|
# whatever
end
См. http://guides.rubyonrails.org/4_0_release_notes.html#active-record
Ответ 4
Это, по-видимому, предупреждение о некорректном предупреждении где-то в Rails. Начиная с Rails 4.0.2 предупреждающее сообщение все еще существует. Я получаю следующую ошибку, когда я пытаюсь запустить Foo.all:
ПРЕДУПРЕЖДЕНИЕ О ДЕПРЕКАЦИИ: Отношение # все устарело. Если ты хочешь eager-load отношение, вы можете вызвать #load (например, Post.where(published:
true).load
). Если вы хотите получить массив записей из отношения, вы можете вызвать #to_a (например, Post.where(published: true).to_a
).
Я почти на 100% уверен, что я смотрел в RailsCasts, что #all был изменен, чтобы возвращать Relation in Rails 4 (вместо массива) - не упоминание об отказе.