Search code examples
rubygetterstring-interpolationinstance-methodsstring-to-symbol

Taking a key from a hash, and interpolate that as a getter on an object


I have a class that creates objects. I've created getter/setter methods for that class.

Class Test

  attr_accessor :method1, :method2, :method3, :method4

I have created several instances from that class, and appended them to a list

@object_array = [obj1, obj2, obj3]

I have a dictionary that contains the keys and values. The keys have the same string value that the instance variables in the test class use. (For example 'method1' exists as :method1) I would like to access those keys as the getter methods.

@method_hash = {'method1' => ['data1','data2'], 'method2' => ['data3','data4']}

I expect this to work, but it isn't. What am I doing wrong?

I should mention that the method below is taking place inside a class and that @object_list and @method_list are themselves instance variables of this second class. (This might not be relevant to solve the issue, but wanted to mention just in case..)

block (2 levels) in func1': undefined method `key' for #<Obj:0x007ffbe1061870> (NoMethodError)

  def func1
    @object_array.each do |o|
      @method_hash.each do |key, value|
        puts o."#{key}"
      end
    end
  end

I tried using .to_s, .to_sym to get it to work with no luck.


Solution

  • puts o."#{key}" is syntactically wrong. You need to fetch the property on runtime. For this you can:

    puts o.instance_variable_get("@#{key}") # dynamically inspect instance variable
    # above will only work if key is instance variable and not a method of o.
    

    or

    puts o.send(key) #dyanmic dispatch
    # will work as long o responds to the key like o.method1.
    

    Update: Prefer o.public_send(key) over send to dynamically dispatch only the publicly accessible method/attribute, as it is safer inspection of object without leaking it's private content.

    If you are sure that is an instance variable, go with the safer first option.