harshs08 harshs08 - 4 months ago 16
Ruby Question

How to handle the case when input to reduce is hash rather than array of hashes

I have an incoming input which is sometimes an array of hashes and sometimes its just an individual hash.

hsh = {"property"=>[{"name"=>"first_name", "value"=>"Joe"}, {"name"=>"last_name", "value"=>"Doe"}]}


or

hsh = {"property"=>{"name"=>"Foo", "value"=>"Bar"}}


From this input I am trying to generate a hash with
name
as
key
and
value
and as
value
, something like this:

hsh['property'].reduce(HashWithIndifferentAccess.new) do |scan, kv_pair|
scan.merge kv_pair['name'] => kv_pair['value']
end


Giving:

{"first_name"=>"Joe", "last_name"=>"Doe"}


This works well when
hsh['property']
is an array of hashes but fails with the following error:

TypeError: no implicit conversion of String into Integer


when it's just an hash.

How do I handle the
reduce
on
hsh['property']
so it handles the case when input to it is hash rather than array of hashes?

Answer

I'd convert the incoming parameter to an array of a single hash, then proceed:

def foo(aoh)
  aoh = [aoh] unless Array === aoh

  aoh # return it so we can see it's been changed

  # do stuff with the AoH
end

foo({a:1}) # => [{:a=>1}]
foo([{a:1},{b:2}]) # => [{:a=>1}, {:b=>2}]

Once it's an array of a single hash, or multiple hashes, you can iterate over the contents of the array with the same code.

If you are responsible for generating the single hash or an array of hashes, you should always generate the same type of object, an array of hashes, which makes it easier for you to deal with it. If you don't, then convert it to the same type of object and move on.