Search code examples
rubyeval

What are the alternatives to eval in Ruby?


I wrote the following recursive function in order to parse some settings and correctly populate some log file objects I have.

When I run this code against Code Climate it tells me that (of course) the use of eval is not encouraged. Is there a way I can rewrite this method so I do not need eval and also do not need a case statement? Nothing comes to mind.

def parse(settings, logfile = nil)
  settings.each do |key, value|
    if value.is_a?(Hash)
      logfile = Logmsg::LogFile.new
      parse(value, logfile)
    else
      eval("logfile.#{key} = value")
    end
  end
end

Any ideas?

I am trying the instance_variable_set meta-programming method however I am still running into some issues with it. For some reason my tests are all failing now due to

Argument Error: comparison of Fixnum with String failed

I am still trying to figure that out.


Solution

  • Since assignment to an object's attribute is just syntactic sugar for a method call (i.e obj.foo = bar is the same as calling the foo= method on obj with the argument bar), use Object#public_send:

    logfile.public_send(:"#{key}=", value)
    

    In older code you often see send instead of public_send, but you should use the latter since it will raise an error if you try to call a private method.