Ruby Metaprogramming: dynamic instance variable names

RubyMetaprogrammingInstance Variables

Ruby Problem Overview


Let's say I have the following hash:

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

How could I dynamically set the keys and values to become instance variables in an object...

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

... so that I end up with the following inside the model...

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

?

Ruby Solutions


Solution 1 - Ruby

The method you are looking for is instance_variable_set. So:

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

Or, more briefly,

hash.each &method(:instance_variable_set)

If your instance variable names are missing the "@" (as they are in the OP's example), you'll need to add them, so it would be more like:

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

Solution 2 - Ruby

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

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

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

Solution 3 - Ruby

You make we want to cry :)

In any case, see Object#instance_variable_get and Object#instance_variable_set.

Happy coding.

Solution 4 - Ruby

You can also use send which prevents the user from setting non-existent instance variables:

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

Use send when in your class there is a setter like attr_accessor for your instance variables:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrewView Question on Stackoverflow
Solution 1 - RubyChuckView Answer on Stackoverflow
Solution 2 - RubyDigitalRossView Answer on Stackoverflow
Solution 3 - Rubyuser166390View Answer on Stackoverflow
Solution 4 - RubyAsarluhiView Answer on Stackoverflow