Something I did with .tap

Huy Phung
Huy Phung
Sep 5, 2018 · 2 min read

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
end

We 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
end

The 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
end

Second 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
end

In 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
end

In 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.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade