Как заполнить 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>
Немного запутанный, но его работа. Я приветствую любые улучшения.