在Rails中为grouped_options_select视图助手生成数组

时间:2014-12-18 11:53:38

标签: ruby arrays ruby-on-rails-4

我有一个Location模型,其namearea属性。我想创建一个选择输入字段,我的选项被分组,如下所示:

<optgroup label="Area1">
   <option value=1>Location 1</option>
   <option value=2>Location 2</option>
   <option value=3>Location 3</option>
</optgroup>
<optgroup label="Area2">
   <option value=4>Location 4</option>
   <option value=5>Location 5</option>
   <option value=6>Location 6</option>
</optgroup>

我在控制器中尝试了以下操作并查看:

控制器:

@grouped_locations = Location.pluck(:area, :name).group_by(&:first).
                  map { |k, v_ary| [k, v_ary.map(&:last)] }.
                  map { |k, v_ary| [k, v_ary.map.with_index { |v, i| [v,i+1] }] }

视图:

<%= f.select :location_id grouped_options_For_select(@grouped_locations)

上面的代码为我提供了一个带有重复值的选择字段,如下所示:

<optgroup label="Area1">
   <option value=1>Location 1</option>
   <option value=2>Location 2</option>
   <option value=3>Location 3</option>
</optgroup>
<optgroup label="Area2">
   <option value=1>Location 4</option>
   <option value=2>Location 5</option>
   <option value=3>Location 6</option>
</optgroup>

如何设置grouped_locations数组以使值不重复,如第一个示例所示?

1 个答案:

答案 0 :(得分:1)

map.with_index部分是索引从每个区域的0开始的位置。所以你需要跟踪索引:

i = 0

@grouped_locations = \
  Location.pluck(:area, :name).group_by(&:first).
  map{ |k, v_ary| [k, v_ary.map(&:last)] }.
  map{ |k, v_ary| [k, v_ary.map{ |v| [v, (i += 1)] }] }

最后两个map可以将BTW合并为一个map

map do |k, v_ary|
  [k, v_ary.map{ |v| [v.last, (i += 1)] }]
end

这应该可以解决问题。

但我建议只使用ID作为值,避免使用多个map来迭代结果。

@grouped_locations = \
  Location.pluck(:area, :id, :name).each_with_object({}) do |location, hash|
    area, id, name = location
    (hash[area] ||= []) << [name, id]
  end.to_a # remove 'to_a' if not required by 'grouped_options_for_select'