2012-01-31 2 views
0

я хочу следующее выбрать тегзаселить выберите тег рубин/рельсы

<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 или

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

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

ответ

3

Для этого вы можете использовать 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, то просто создать этот класс экземпляры внутри сборным/метод отображения:

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 (похоже, это так для рубин 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') 

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

+0

thnx Alex .. также вы можете предложить какую-нибудь книгу или ссылку для начала с структурами данных и метапрограммированием в рубине .. это будет действительно полезно.В настоящее время я работаю над некоторым проектом рельсов и часто должен использовать выше структуры. –

+0

@mashit, на мой взгляд, лучшим местом для стильной библиотеки базового класса является [ruby-doc.org] (http://ruby-doc.org/core-1.9.3/). Если вы хотите изучать рубин глубже, я могу порекомендовать * The Ruby Programing Language * Matz. И для более глубокого понимания метапрограммирования вы можете проверить книгу * Метапрограммирование Ruby * Perotta. –

+0

Да, я требовал, чтобы (ваш второй ответ) –

1
array = [["0 %", 0], ["10 %", 10], ["20 %", 20], ["30 %", 30]] 
@arr = array.collect { |sub_array| Ratio.new(:id=>sub_array.last, :name=>sub_array.first) } 
+0

Я не следую классу. i.e я не использую Ratio class –

+0

Друг, я думал, что вы используете класс Ratio.Okay no issues :) –

+0

well thnx any ways –

Смежные вопросы