A pitfall of the &. operator in Ruby

Posted by Anton Katunin on 4 November 2017
Tags: code, ruby, ruby_weekly

Update 1: The article was translated to Japanese

Update 2: This post is featured in RubyWeekly #374

The &. operator, added to Ruby 2.3, is handy and I’ve cleaned a lot of code with it. You can use it in conjunction with default operators as described in Ruby's New &.!= Operator.

Recently I introduced a bug when using &.. First we had:

if start_date && start_date < start_of_month && end_date.nil?
  # …
end

I refactored it to use &.:

if start_date &.< start_of_month && end_date.nil?
  # …
end

The new version looked cleaner. But do you see the bug? Have a look with parenthesis to see the order of execution:

if start_date &.< (start_of_month && end_date.nil?)
  # …
end

The issue is that after I introduced &., the special operator < became a normal method call. The right hand side of &.< are considered to be method arguments and are executed first.

To fix it we must wrap the first part with parenthesis:

if (start_date &.< start_of_month) && end_date.nil?
  # …
end

The next time you refactor to &. operator, keep in mind the change of the behavior.