Ruby: Returning hashes using merge! and merge
We came across an interesting problem today with some code which was unexpectedly returning nil.
The code that we had looked like this…
class SomeClass
def our_method
a_hash = { :a => 2 }
a_hash.merge!({:b => 3}) unless some_condition.nil?
end
end
…and we didn’t notice the 'unless' statement on the end which meant that if 'some_condition' was nil then the return value of the method would be nil.
One way around it is to ensure that we explicitly return a_hash at the end of the method…
class SomeClass
def our_method
a_hash = { :a => 2 }
a_hash.merge!({:b => 3}) unless some_condition.nil?
a_hash
end
end
…but I think that looks a bit ugly.
Luckily Rails provides a method called 'returning' which I first learnt about from Reg Braithwaite’s blog post about the kestrel combinator.
That method is defined like so:
def returning(value)
yield(value)
value
end
And we can use it in our code like this:
class SomeClass
def our_method
a_hash = { :a => 2 }
returning a_hash do |h|
h..merge!({:b => 3}) unless some_condition.nil?
end
end
end
Another way to return the merged hash without mutating the original would be to use the 'merge' method rather than 'merge!':
class SomeClass
def our_method
a_hash = { :a => 2 }
a.hash.merge(!some_condition.nil? ? {:b => 3} : {})
end
end
We could use that approach with 'merge!' as well but I’m not sure that it reads as nicely as the version which uses the 'unless' way.
Another approach that I started messing around with could be this…
class SomeClass
def our_method
a_hash = { :a => 2 }
merge_unless(a_hash, {:b => 3}, proc { some_condition.nil? })
end
end
def merge_unless(hash, other_hash, condition)
if condition.call()
hash
else
hash.merge(other_hash)
end
end
…although that’s probably a bit over the top seeing the collection of other ways we already have.
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.