Something I did with .tap
I have worked with Ruby on Rails for more than 15 months but I rarely use .tap method. In the last week, I found out that it is useful for some cases and it can cause some trouble if you do not really understand how the codes work actually.
.tap code in Ruby show below:
class Object
def tap
yield self
self
end
endWe use .tap when we called some methods on an object but we do not want to get the final value but the object instead. And in the last week, I encountered two cases that I have to use .tap
First case
I have the codes below:
def update_info(info)
user = User.find_by(name: info[:name])
user.address = info[:address]
user.phone_number = info[:phone_number]
user.save!
user
endThe purposes of this method are:
- Update the user object and save it to the database
- Return the user object after save
But I do not want to return the object like that. The user line at the end of that method seems extraneous. So, we can clean it up with the new implementation below:
def update_info(info)
User.find_by(name: info[:name]).tap do |u|
u.address = info[:address]
u.phone_number = info[:phone_number]
u.save!
end
endSecond case
In the second case I made a mistake when using tap with assignment. The original code of second case is:
def my_elements
elements = []
elements += FIRST_ELEMENTS if first_condition
elements += SECOND_ELEMENTS if second_condition
elements
endIn the first try, I made a mistake by refactor the code like this:
def my_elements
[].tap do |elements|
elements += FIRST_ELEMENTS if first_condition
elements += SECOND_ELEMENTS if second_condition
end
endIn this case the elements is pointing to the array object but if we use assignment here, it do not mutate the original array, it will only change the pointer of elements to the new array it is assign. But in the end, .tap will return the original array and in this case, it always return an empty array.
So I try another thing to solve this problem. Instead of using assignment like the origin codes. I used .concat . Concat will mutate the current array by appending the elements of other array to itself. Finally, .tap will return the correct result that we want.
Conclusion
By go through the two cases above I hope I shared some good experiences about using .tap . This method is very good to make your codes look cleaner. However, we need to notice the result it return. I suggest write the unit tests first before we refactor any codes.
