【问题标题】:populate select tag ruby/rails填充选择标签 ruby​​/rails
【发布时间】:2012-01-31 12:23:00
【问题描述】:

我想关注选择标签

<select>
<option value=10> 10% </option>
<option value=20> 20% </option>
<option value=30> 30% </option>
</select>

使用

 ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] })

会给出类似

的结构
[["0 %", 0], ["10 %", 10], ["20 %", 20], ["30 %", 30]]

我想知道这个结构是否可以转换成这样的东西

[#<ratio id: 10, name: "10%">, #<id: 20, name:"20%">]

如何将第一个结构转换为第二个结构

所以我可以使用

options_from_collection_for_select(@arr,"id","name")

填充 select_tag 或

有没有更好的方法来做同样的事情?

请参加。

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    您可以尝试使用OpenStruct

    OpenStruct 是一种类似于 Hash 的数据结构,它允许 任意属性的定义及其伴随值。 这是通过使用 Ruby 的元编程来定义方法来完成的 类本身。

    require 'ostruct'
    (0..10).map { |i| OpenStruct.new(:id => i*10, :name => "#{i*10}%") }
    # => [#<OpenStruct id=0, name="0%">, #<OpenStruct id=10, name="10%">, ...
    

    但是如果你需要一个真正的类,而不是像 OpenStruct 这样的匿名类,那么只需在 collect/map 方法中创建这个类实例:

    class Ratio
        attr_reader :id, :name
        def initialize(id, name)
            @id = id; @name = name
        end
    end
    (0..10).map { |i| ratio = i*10; Ratio.new(ratio, "#{ratio}%") }
    # => [#<Ratio: @id=0, @name="0%">, #<Ratio: @id=10, @name="10%">, ...
    

    也许我对你有点误解,你想创建这个结构不是从范围,而是从数组[["0 %", 0], ["10 %", 10], ["20 %", 20], ["30 %", 30]] 那么代码是相似的:

    require 'ostruct'
    arr = [["0 %", 0], ["10 %", 10], ["20 %", 20], ["30 %", 30]]
    p arr.map { |name, id| OpenStruct.new(:id => id, :name => name) }
    # => [#<OpenStruct id=0, name="0 %">, #<OpenStruct id=10, name="10 %">, #<OpenStruct id=20, name="20 %">, #<OpenStruct id=30, name="30 %">]
    

    更新 我在使用 OpenStruct 时发现了一个极端情况(看起来这仅适用于 Ruby 1.8.7):OpenStruct#id 将返回 object_id 以获取 id 而不是字段值:

    ruby-1.8.7-p352 > o = OpenStruct.new :id => 10
     => #<OpenStruct id=10> 
    ruby-1.8.7-p352 > o.id
    (irb):4: warning: Object#id will be deprecated; use Object#object_id
     => 70021843187380 
    

    有两种解决方法:

    # 1. redefine OpenStruct#id method: 
    OpenStruct.__send__(:define_method, :id) { @table[:id] }
    
    # 2. dont use 'id' as a value and use any other value:
    require 'ostruct'
    (0..10).map { |i| OpenStruct.new(:value => i*10, :name => "#{i*10}%") } # 'value' instead of 'id'
    
    ...
    options_from_collection_for_select(@arr, 'value', 'name')
    

    我建议你使用第二种方法。

    【讨论】:

    • thnx Alex .. 你还可以推荐一些书籍或参考资料来开始使用 ruby​​ 中的数据结构和元编程.. 这将非常有帮助。我目前正在做一些 Rails 项目,经常需要使用上述结构。
    • @mashit,在我看来,整理基类库的最佳位置是ruby-doc.org。如果你想更深入地学习 ruby​​,我可以推荐 Matz 的 The Ruby Programming Language。为了更深入地了解元编程,您可以查看 Perotta 的 Metaprogramming Ruby 一书。
    • 嗯,生成的 html 的 id 有问题 - .. 我正在使用
    • 还有如何在新结构中找到一个元素(使用openStruct创建的那个)
    • @mashit,如何找到:@arr.find {|obj| obj.id == 20 } # =&gt; #&lt;OpenStruct id=20, name="20%"&gt;
    【解决方案2】:
    array = [["0 %", 0], ["10 %", 10], ["20 %", 20], ["30 %", 30]]
    @arr = array.collect { |sub_array| Ratio.new(:id=>sub_array.last, :name=>sub_array.first) }
    

    【讨论】:

    • 我不上课了。即我没有使用 Ratio 类
    • 朋友,我以为你在使用 Ratio 类。好吧,没问题 :)