2011-01-18 3 views
5

Я хочу преобразовать хэш в объект с использованием OpenStruct, который имеет свойство id, однако полученный object#id возвращает собственный идентификатор объекта, например.Переопределить идентификатор на ruby-объекте (созданный с использованием OpenStruct)

test = OpenStruct.new({:id => 666}) 
test.id # => 70262018230400 

Есть ли способ обойти это? На данный момент мое обходное решение не так красиво.

ответ

6

OpenStruct использует комбинацию define_method вызовов внутри unless self.respond_to?(name) проверки и method_missing. Это означает, что если имя свойства конфликтует с именем любого существующего метода на объекте, тогда вы столкнетесь с этой проблемой.

tokland's ответ, если хороший, но другой вариант заключается в том, чтобы определить метод id, например.

test.instance_eval('undef id') 

Вы также могли бы включить это в свою собственную настроенную версию OpenStruct например,

class OpenStruct2 < OpenStruct 
    undef id 
end 

irb(main):009:0> test2 = OpenStruct2.new({:id => 666}) 
=> #<OpenStruct2 id=666> 
irb(main):010:0> test2.id 
=> 666 
+0

Это звучит хорошо, вы не зависят от любой переменной экземпляра (@table, которая может быть реорганизована). – tokland

1

Это был классический обходной путь, я бы тоже рад услышать лучший способ:

>> OpenStruct.send(:define_method, :id) { @table[:id] } 
=> #<Proc:[email protected](irb):1> 
>> OpenStruct.new(:id => 666).id 
=> 666 
0

Я перешел на использование Hashery и BasicStruct (переименованную версию OpenObject в последней версии, 1.4), что и позволяет мне сделать это:

x = BasicStruct.new({:id => 666, :sub => BasicStruct.new({:foo => 'bar', :id => 777})}) 
x.id  # => 666 
x.sub.id # => 777 
x.sub.foo # => "bar" 
Смежные вопросы