Метапрограммирование Ruby: имена переменных динамических экземпляров - PullRequest
88 голосов
/ 19 июля 2011

Допустим, у меня есть следующий хэш:

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

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

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

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

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

Ответы [ 4 ]

164 голосов
/ 19 июля 2011

Метод, который вы ищете: 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) }
12 голосов
/ 19 июля 2011
h = { :foo => 'bar', :baz => 'qux' }

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

o.baz
 => "qux" 
o.foo
 => "bar" 
7 голосов
/ 19 июля 2011

Вы заставляете нас плакать:)

В любом случае смотрите Object#instance_variable_get и Object#instance_variable_set.

Удачного кодирования.

5 голосов
/ 20 октября 2015

Вы также можете использовать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...