Use thing.send("#{k}=", v)
instead.
Dynamically assigning attributes using strings as attribute setters in Ruby
-
04-07-2022 - |
Question
I have a hash of name / value pairs:
attr_hash = {"attr1"=>"val1","attr2=>"val2"}
I want to cycle through each one of these values and assign them to an object like so:
thing = Thing.new
attr_hash.each do |k,v|
thing.k = v
end
class Thing
attr_accessor :attr1, :attr2
end
The problem of course being that attr1 is and attr2 are strings.. So I can't do something like thing."attr1"
I've tried doing:
thing.send(k,v)
but that doesn't work
La solution
Autres conseils
You need to call the setter method, which for an attribute called name
would be name=
.
Following from your example:
attr_hash.each do |k,v|
thing.send("#{k}=", v)
end
Also, if this hash is coming from the user somehow, it might be a good idea to test if the setter exists before calling it, using respond_to?
:
attr_hash.each do |k,v|
setter = "#{k}="
thing.send(setter, v) if thing.respond_to?(setter)
end
OpenStruct does it for you.
require 'ostruct'
attr_hash = {"attr1"=>"val1", "attr2"=>"val2"}
d = OpenStruct.new(attr_hash)
p d.attr1 #=> "val1"
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow