0

I have an array of hashes, which I would rather be turned into an array of objects with attributes programmatically added to those objects.

I'm try this at the moment

obj = OpenStruct.new

resulthash["users"].collect { |u|
  u.each do |k,v|
    obj.send("#{k}=#{v}");
  end
}

To recap I'm trying to do

obj.foo = "bar"
obj.hello = "world"

But programmatically if for example to the array/hash looked liked this

{"users"=>[{"foo"=>"bar","hello"=>"world"}]}
Joseph Le Brech
  • 6,541
  • 11
  • 49
  • 84

1 Answers1

5

Object#send takes a method name as the first argument and optionally arguments to pass to the method as the remaining arguments.

Thus, obj.send("#{k}=#{v}") really tries to call methods named something like "foo=bar", which is not the same as calling foo= with an argument "bar".

So for one, the right way would be

resulthash["users"].each { |u|
  u.each do |k,v|
    obj.send("#{k}=", v)
  end
}

Note that I am using #each and not #collect because we do not want to transform the Hash.

Also, if your example reflects your final goal of just converting an array of Hashes into a single OpenStruct, you can just combine all Hashes into one and pass that to OpenStruct.new:

h = resulthash["users"].inject({}) { |acc, v| acc.merge(v) }
obj = OpenStruct.new(h)
Dominik Honnef
  • 17,937
  • 7
  • 41
  • 43