заполнить выберите тег ruby ​​/ rails - PullRequest
0 голосов
/ 31 января 2012

Я хочу следовать выбранному тегу

<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%">]

как преобразовать первую структуру во второе strcuture

чтобы я мог использовать

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

для заполнения тега select_tag или

Есть ли лучший способ сделать то же самое?

комментируйте пожалуйста.

Ответы [ 2 ]

3 голосов
/ 31 января 2012

Вы можете попробовать использовать 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 %">]

UPDATE Я нашел один угловой случай при использовании 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')

Я рекомендую вам использовать второй подход.

1 голос
/ 31 января 2012
array = [["0 %", 0], ["10 %", 10], ["20 %", 20], ["30 %", 30]]
@arr = array.collect { |sub_array| Ratio.new(:id=>sub_array.last, :name=>sub_array.first) }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...