Как заполнить select_tag массивом хэшей?

В приложении Rails 3.2 я пытаюсь добавить поле выбора, которое берет его данные из внешнего вызова API. Эти данные возвращаются как массив хэшей:

[{"name"=>"NameA", "id"=>"001"}, {"name"=>"NameB", "id"=>"002"}]

Как я могу использовать эти данные для построения поля выбора, которое выглядит примерно так:

<select>
  <option value="001"> NameA </option>
  <option value="002"> NameB </option>
</select>

EDIT:

Благодаря приведенным ниже предложениям я пробовал следующее:

А:

<%= select_tag 'model[field]', options_from_collection_for_select(@hash, :id, :name) %>

Дает ошибку:

undefined method `name' for {"name"=>"NameA", "id"=>"001"}:Hash

В:

<%= select_tag 'model[field]', options_from_collection_for_select(@hash) %>

Исправляет ошибку, но генерирует неправильную разметку

<option value="{"name"=>"NameA", "id"=>"001"}"> {"name"=>"NameA", "id"=>"001"}</option>

Итак, я думаю, что моя проблема заключается в правильном форматировании массива хэшей, и я не знаю достаточно о том, как манипулировать массивами хешей, чтобы решить, как это сделать.

Если я полностью не посмотрю на worng-направление, я думаю, что ключом к этой проблеме является переформатирование массива в верхней части этого вопроса, чтобы дать:

{"NameA" =>"001", "NameB" =>"002"}

Возможно ли это? И если да, то как?

Ответы

Ответ 1

Лучший способ сделать это только одной командой:

<%= select_tag "model[field]", options_for_select(@array_of_hashes.map { |obj| [obj['name'], obj['id']] }) %>

С вашим примером хэша:

irb> @array_of_hashes = [{"name"=>"NameA", "id"=>"001"}, {"name"=>"NameB", "id"=>"002"}]
=> [{"name"=>"NameA", "id"=>"001"}, {"name"=>"NameB", "id"=>"002"}]
irb> @array_of_hashes.map { |obj| [obj['name'], obj['id']] }
=> [["NameA", "001"], ["NameB", "002"]]

Ответ 2

Если у вас есть массив хешей, например:

@people = [{"name"=>"NameA", "id"=>"001"}, {"name"=>"NameB", "id"=>"002"}]

Вы можете использовать options_for_select помощник collect, например:

= select_tag "people", options_for_select(@people.collect {|p| [ p['name'], p['id'] ] })

И его сделано: -).

Ответ 3

Вы можете использовать options_for_select для этой цели. Требуется двумерный массив. Вы можете преобразовать свой хэш следующим образом:

data = [{"name"=>"NameA", "id"=>"001"}, {"name"=>"NameB", "id"=>"002"}]
data_for_select = data.each { |hash| [hash['name'], hash['id']] }
options_for_select(data_for_select)

Как примечание к options_from_collection_for_select, оно используется в сочетании с объектами. Он выполняет итерацию через объекты и отправляет сообщение для метки и один для идентификатора.

Ответ 4

Самый простой способ использования хэшей в selects, для меня:

Хеш:

REVISION_TYPES={"S"=>"Stock", "T"=>"Traducción"}

В форме:

select_tag(:revision_type,options_for_select(REVISION_TYPES.invert.to_a))

Ответ 5

Хорошо, я в конечном итоге выяснил решение, которое работает, хотя оно может и не быть лучшим.

$ @array_of_hashes = [{"name"=>"NameA", "id"=>"001"}, {"name"=>"NameB", "id"=>"002"}]
=> [{"name"=>"NameA", "id"=>"001"}, {"name"=>"NameB", "id"=>"002"}]
$ @formatted_array_of_hashes = @array_of_hashes.each.map{ |h| { h["name"] => h["id"] }}
=> [{"NameA" => "001"}, {"NameB" => "002"}]
$ @merged_hash = Hash[*@formatted_array_of_hashes.map(&:to_a).flatten]
=> {"NameA" => "001", "NameB" => "002"}

Тогда я смог создать поле выбора

<%= select_tag 'model[field]', options_for_select(@merged_hash) %>

который генерирует правильную разметку

<select>
  <option value="001">NameA</option>
  <option value="002">NameB</option>
</select>

Немного запутанный, но его работа. Я приветствую любые улучшения.