Как я могу повернуть:
Person.all.pluck(:id, :name)
к
[{id: 1, name: 'joe'}, {id: 2, name: 'martin'}]
без необходимости .map каждое значение (поскольку, когда я добавляю или удаляю из .pluck, я должен делать то же самое с .map)
Как я могу повернуть:
Person.all.pluck(:id, :name)
к
[{id: 1, name: 'joe'}, {id: 2, name: 'martin'}]
без необходимости .map каждое значение (поскольку, когда я добавляю или удаляю из .pluck, я должен делать то же самое с .map)
Вы могли бы просто сделать это
Person.select(:id,:name).as_json
Вы также можете попробовать это.
Person.all.as_json(only: [:id, :name])
Вы можете map
получить результат:
Person.all.pluck(:id, :name).map { |id, name| {id: id, name: name}}
Как уже упоминалось @alebian: Это более эффективно, чем
Person.all.as_json(only: [:id, :name])
Причины:
pluck
возвращает только используемые столбцы (: id,: name), тогда как другое решение возвращает все столбцы. В зависимости от ширины таблицы (количество столбцов) это имеет большое значение.Person
, не требует назначения атрибутов для моделей и т.д. Вместо этого он просто возвращает массив с одним целым числом и одной строкой.as_json
снова имеет больше накладных расходов, чем простой map
, поскольку это общая реализация для преобразования модели в хэшЯ вижу три варианта:
1) pluck
плюс map
:
Person.pluck(:id, :name).map { |p| { id: p[0], name: p[1] } }
2) pluck
плюс map
плюс zip
и переменная, чтобы сделать его DRY-er:
attrs = %w(id name)
Person.pluck(*attrs).map { |p| attrs.zip(p).to_h }
3) или вы вообще не можете использовать pluck
, хотя это гораздо менее эффективно:
Person.all.map { |p| p.slice(:id, :name) }
Если вы используете postgresql, вы можете использовать функцию json_build_object
в методе pluck:
https://www.postgresql.org/docs/9.5/functions-json.html
Таким образом, вы можете позволить БД создавать хэши.
Person.pluck("json_build_object('id', id, 'name', name)")
#=> [{id: 1, name: 'joe'}, {id: 2, name: 'martin'}]
Мог бы пойти на хэш после того, как скрепок с идентификатором будет ключ, а Name будет значением:
Person.all.pluck(:id, :name).to_h
{ 1 => 'joe', 2 => 'martin' }
Не уверен, что это соответствует вашим потребностям, но представляет в качестве опции.
Для этого можно использовать метку pluck_to_hash с меткой имен: https://github.com/girishso/pluck_to_hash
Он будет расширять AR с помощью метода pluck_to_hash, который работает следующим образом:
Post.limit(2).pluck_to_hash(:id, :title)
#
# [{:id=>213, :title=>"foo"}, {:id=>214, :title=>"bar"}]
#
Post.limit(2).pluck_to_hash(:id)
#
# [{:id=>213}, {:id=>214}]
Он утверждает, что он в несколько раз быстрее, чем при использовании AR select
и as_json
Существует драгоценный камень pluck_all, который делает почти то же самое, что и pluck_to_hash. И это утверждает, что это на 30% быстрее. (см. тест здесь).
Использование:
Person.pluck_all(:id, :name)
Если у вас есть несколько атрибутов, вы можете сделать это для чистоты:
Item.pluck(:id, :name, :description, :cost, :images).map do |item|
{
id: item[0],
name: item[1],
description: item[2],
cost: item[3],
images: item[4]
}
end