2010-09-23 5 views

ответ

24

Если вы хотите сделать «динамический» формальный класс, используйте Struct:

>> Person = Struct.new(:name, :phone) 
=> Person 
>> bob = Person.new("bob", "555-1212") 
=> #<struct Person name="bob", phone="555-1212"> 
>> bob.name 
=> "bob" 
>> bob.phone 
=> "555-1212" 

Чтобы сделать объект полностью на лету из хэша, используйте OpenStruct:

>> require 'ostruct' 
=> true 
>> bob = OpenStruct.new({ :name => "bob", :phone => "555-1212" }) 
=> #<OpenStruct phone="555-1212", name="bob"> 
>> bob.name 
=> "bob" 
>> bob.phone 
=> "555-1212" 
+1

насчет делать что-то вроде 'Бобом = Object.new'? –

3

Один из многих способов сделать это - использовать class_eval, define_method и т. Д. Для динамического построения класса:

dynamic_properties = { 
    'name' => 'bob', 
    'phone' => '555-1212' 
} 

class_instance = Object.const_set('MyClass', Class.new) 
class_instance.class_eval do 
    define_method(:initialize) do 
    dynamic_properties.each do |key, value| 
     instance_variable_set("@#{key}", value); 
    end 
    end 

    dynamic_properties.each do |key, value| 
    attr_accessor key 
    end 
end 

Вы можете потреблять этот класс позже следующим образом:

>> my_object = MyClass.new 
>> puts my_object.name 
=> 'bob' 
>> puts my_object.phone 
=> '555-1212' 

Но это не было бы Руби, если есть только один способ сделать это!

+2

чувак, который важен !!! – horseyguy

+0

Это совершенно отвратительно, я согласен! Просто проиллюстрируем, что есть несколько разных способов сделать что-то - я также вполне уверен, что это то, что «Struct» и «OpenStruct» делают под обложками. –

4

Использование OpenStruct:

require 'ostruct' 

data = { :name => "bob", :phone => "555-1212" } 
my_object = OpenStruct.new(data) 

my_object.name #=> "bob" 
my_object.phone #=> "555-1212"