WIP
One of the problems I've faced recently was a ruby class that heavily used merge!
through all their methods.
If you don't know what .merge
do, let me explain it first:
If you have a ruby hash and want to add a new key with a value you have two ways to do it:
product = {
sku: 'SKU1234567'
}
# first way
product[:title] = 'Yoyo'
product[:description] = 'An awesome Yoyo'
#or
# second way
product = product.merge(
title: 'Yoyo',
description: 'An awesome Yoyo'
)
product[:title] # 'Yoyo'
product[:description] # 'An awesome Yoyo'
As you can see, the first way seem to be much more easy to read because there is an assignment for every value we want to provide to product
. The second way doesn't seem too complicated but it can make our work easier when we want to merge two hashes together to pass to another class or method.
And how does .merge!
behave? What's the difference between .merge
and .merge!
?
Well, .merge
and .merge!
have the same behavior except for one thing. While .merge
returns a new merged hash, .merge!
modifies the actual hash that invoked the method.
Let me show you an example:
# If we have again:
product = {
sku: 'SKU1234567'
}
# Using .merge
product.merge(title: 'Yoyo')
product[:title] # nil
# Using .merge!
product.merge!(title: 'Yoyo')
product[:title] # 'Yoyo'
As you can see if we invoke the method .merge!
we don't need to assign the return of the method in order to keep the value generated by it.
So it looks like merge!
is actually a pretty hand method right? But problems/complexity arise if we use merge!
. Problems like your hash modifying/adding/deleting your keys without you expecting it could raise bugs that are really hard to track as well as making it harder to do refactoring.
So how we can avoid this? Well, the first thing would be to not use methods that mutates the current hash. Also, do not change the hash if you received it as a parameter to your class/module.
You could also .freeze
your hash to avoid it being mutated, raising the RuntimeError: can't modify frozen Hash
exception.
sources: https://thoughtbot.com/upcase/videos/mutation-in-ruby http://vaidehijoshi.github.io/blog/2015/03/03/bundle-up-and-let-your-objects-do-the-freezing-frozen-hashes/