Ruby Metaprogramming: имена переменных динамического экземпляра

Скажем, у меня следующий хэш:

{ :foo => 'bar', :baz => 'qux' }

Как я могу динамически установить ключи и значения, чтобы стать переменными экземпляра в объекте...

class Example
  def initialize( hash )
    ... magic happens here...
  end
end

... так что я получаю следующее внутри модели...

@foo = 'bar'
@baz = 'qux'

?

Ответ 1

Метод, который вы ищете, instance_variable_set. Итак:

hash.each { |name, value| instance_variable_set(name, value) }

Или, более кратко,

hash.each &method(:instance_variable_set)

Если в именах переменных экземпляра отсутствует значение "@" (как показано в примере OP), вам нужно будет добавить их, так что это будет больше похоже на:

hash.each { |name, value| instance_variable_set("@#{name}", value) }

Ответ 2

h = { :foo => 'bar', :baz => 'qux' }

o = Struct.new(*h.keys).new(*h.values)

o.baz
 => "qux" 
o.foo
 => "bar" 

Ответ 4

Вы также можете использовать send, который запрещает пользователю устанавливать несуществующие переменные экземпляра:

def initialize(hash)
  hash.each { |key, value| send("#{key}=", value) }
end

Используйте send, когда в вашем классе есть наборщик, например attr_accessor для ваших переменных экземпляра:

class Example
  attr_accessor :foo, :baz
  def initialize(hash)
    hash.each { |key, value| send("#{key}=", value) }
  end
end