Take this answer with a grain of salt because I'm no expert on Ruby's eval, but this worked for me:
require 'json'
hash = '{"$a":5,"b":10}'
hash1 = JSON.parse(hash)
bind = binding
hash1.each do |k,v|
# Dunno what this is for and things work fine without it.
# singleton_class.send(:attr_accessor,k)
# You don't want to call `send` here, just call `eval` directly.
eval("#{k}=#{v}", bind)
end
puts $a
# => 5
puts b
# => 10
Note that I'm passing in a binding from the parent scope to eval since you'll want to access local variables such as b in the parent scope after you exit the loop.
Lastly, v needed to be part of the string passed to eval, not the second parameter passed to eval, which, if anything, needs to be a binding. If you pass an integer it will raise an exception.
However, I should warn you that global variables should be used with restraint, and that using eval can be dangerous, especially if you get this JSON from someone else.
evalmakes me think if is there is a better way to do that and if this leads to a security vulnerability. Perhaps working directly with the hash would be a better idea?