DEV Community

Junko T.
Junko T.

Posted on

9 2

Ruby iteration shortcut with &(ampersand) operator

Ruby logo

One of the reasons why Ruby is my favorite language is that it has many shortcuts and can do a lot with a few lines of code. & (ampersand) operator is one great example.

A quick explanation of how & works in Ruby:

# These two calls are equivalent:

numbers.select { |number| number.even? }

numbers.select(&:even?)
Enter fullscreen mode Exit fullscreen mode

& calls the to_proc method on the following object which is a symbol :even? in the example above. (the to_proc method is implemented on symbols.) This means the object will be encapsulated as a block of code (as a Proc object), and then passed to the given method.

This might still look weird to you as it did to me in the beginning because .even? is a built-in method in Ruby. Why can I use it as a symbol? This works because method names in Ruby are internally stored as symbols. For the same reason, you can use this & shortcut for the methods you define as well.

Let's see the examples with Ruby Enumerable that you use everyday:

1. find

# Returns the first admin user

# BAD
def find_admin(users)
  users.find { |user| user.admin? }
end

# GOOD
def find_admin(users)
  users.find(&:admin?)
end
Enter fullscreen mode Exit fullscreen mode

2. select

# Returns all the admin users

# BAD
def find_admins(users)
  admins = []
  users.each do |user|
    admins << user if user.admin?
  end
  admins
end

# GOOD
def find_admins(users)
  users.select(&:admin?)
end
Enter fullscreen mode Exit fullscreen mode

3. count

# Returns the number of the admin users

# BAD
def count_admin(users)
  count = 0
  users.each do |user|
    count += 1 if user.admin?
  end
  count
end

# GOOD
def count_admin(users)
  users.count(&:admin?)
end
Enter fullscreen mode Exit fullscreen mode

4. map

# Returns an array of each user's name

# BAD
def user_names(users)
  names = []
  users.each do |user|
    names << user.name
  end
  names
end

# GOOD
def user_names(users)
  users.map(&:name)
end
Enter fullscreen mode Exit fullscreen mode

5. any?

# Returns true if at least one user exists.

# BAD
def contains_nil?(users)
  users.each do |user|
    return true if user.nil?
  end
  false
end

# GOOD
def contains_nil?(users)
  users.any?(&:nil?)
end
Enter fullscreen mode Exit fullscreen mode

6. max/max_by

# Returns the oldest user.

# BAD
def oldest_user(users)
  oldest = nil
  users.each do |user|
    oldest = user if oldest.nil? || user.age > oldest.age
  end
  oldet
end

# GOOD
def oldest_user(users)
  users.max_by(&:age)
end
Enter fullscreen mode Exit fullscreen mode

Knowing this, when you iterate over an array using a block where you simply return object.method, you will notice code smells and consider using & operator instead.

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (2)

Collapse
 
sabarishcodes profile image
Sabarish Rajamohan

Nice list of methods to use !!! Thank you

Collapse
 
junko911 profile image
Junko T.

Thank you for reading!

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay