Ruby on Rails 4: результаты pluck для хеша

Как я могу повернуть:

Person.all.pluck(:id, :name)

к

[{id: 1, name: 'joe'}, {id: 2, name: 'martin'}]

без необходимости .map каждое значение (поскольку, когда я добавляю или удаляю из .pluck, я должен делать то же самое с .map)

Ответ 1

Вы могли бы просто сделать это

Person.select(:id,:name).as_json

Вы также можете попробовать это.

Person.all.as_json(only: [:id, :name])

Ответ 2

Вы можете map получить результат:

Person.all.pluck(:id, :name).map { |id, name| {id: id, name: name}}

Как уже упоминалось @alebian: Это более эффективно, чем

Person.all.as_json(only: [:id, :name])

Причины:

  • pluck возвращает только используемые столбцы (: id,: name), тогда как другое решение возвращает все столбцы. В зависимости от ширины таблицы (количество столбцов) это имеет большое значение.
  • Решение pluck не создает объекты Person, не требует назначения атрибутов для моделей и т.д. Вместо этого он просто возвращает массив с одним целым числом и одной строкой.
  • as_json снова имеет больше накладных расходов, чем простой map, поскольку это общая реализация для преобразования модели в хэш

Ответ 3

Я вижу три варианта:

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) }

Ответ 4

Если вы используете 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'}]

Ответ 5

Мог бы пойти на хэш после того, как скрепок с идентификатором будет ключ, а Name будет значением:

Person.all.pluck(:id, :name).to_h

{ 1 => 'joe', 2 => 'martin' }

Не уверен, что это соответствует вашим потребностям, но представляет в качестве опции.

Ответ 6

Для этого можно использовать метку 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

Ответ 8

Если у вас есть несколько атрибутов, вы можете сделать это для чистоты:

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