I am trying to dynamically define methods on an initialized Ruby object MyObject
based on a hash my_hash
I pass to its initialize
method. In the body of the initialize
method, I have the following:
my_hash.each do |key|
class << self
define_method(key.underscore.to_sym) do
my_hash[key]
end
end
end
This fails with a undefined local variable or method 'key' for #<Class:#<MyObject:0x007fc7abw0cra0>>
. Any ideas why?
The my_hash
is made out of a json response with a lot of camelized keys, so it's more convenient to have simple ruby methods to get the values I want.
Local variables are local to the scope they are defined in. The (lexical) scopes in Ruby are script scope, module/class definition scope, method definition scope and block scope. Only block scopes nest in their outer scopes (aka close over their surrounding scope). So, you have to use a block:
my_hash.each_key do |key|
singleton_class.class_eval do
define_method(key.to_sym) do
my_hash[key]
end
end
end
Or even better yet:
my_hash.each_key do |key|
define_singleton_method(key.underscore.to_sym) do
my_hash[key]
end
end
Note: I also fixed a bug, you should be iterating the keys with each_key
, not each
(which is an alias for each_pair
).