Métaprogrammation Ruby: noms de variables d’instances dynamics

Disons que j’ai le hachage suivant:

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

Comment pourrais-je définir dynamicment les clés et les valeurs pour qu’elles deviennent des variables d’instance dans un object …

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

… pour que je me retrouve avec les éléments suivants dans le modèle …

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

?

La méthode que vous recherchez est instance_variable_set . Alors:

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

Ou, plus brièvement,

 hash.each &method(:instance_variable_set) 

Si les noms de variables de votre instance ne contiennent pas le “@” (comme dans l’exemple de l’OP), vous devrez les append, cela ressemblera davantage à:

 hash.each { |name, value| instance_variable_set("@#{name}", value) } 
 h = { :foo => 'bar', :baz => 'qux' } o = Struct.new(*h.keys).new(*h.values) o.baz => "qux" o.foo => "bar" 

Tu fais envie de pleurer 🙂

Dans tous les cas, voir Object#instance_variable_get et Object#instance_variable_set .

Heureux codage

Vous pouvez également utiliser send qui empêche l’utilisateur de définir des variables d’instance inexistantes:

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

Utilisez send quand dans votre classe il y a un setter comme attr_accessor pour vos variables d’instance:

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