Megan Tiu

Megan Tiu

My tw2 32px My li2 Email

Ruby's Enumerable Module and You

May 29, 2016

When was the last time you explored Ruby's Enumerable module?

Want to get more control over your data? Of course you do. Thankfully, you're in luck! Enumerable is included anywhere you can use an #each method. Arrays? Yup. Hashes? You bet. You can even use it in your own custom classes. Discovering this module was a big level-up for me–all of a sudden, I could accomplish more in fewer lines of code. I could read my data-concerned code easier. I could lift a horse with my newfound power! (Okay, that last one's probably not true. But still, the Enumerable module is pretty great.)

Here are a few of my favorite ways to use the Enumerable module:

Checking a Collection Against a Condition

All of the following methods accept any block of code that returns a boolean and will tell you if the block returns true for the specified amount of items in the collection.

#any?

any? checks to see if at least one item in a collection meets the specified condition and returns a boolean based on its findings.

[1, 2, 3].any? { |i| i == 3 } => true

#all?

Similar to any?, all? checks if every item meets the passed condition.

[1, 2, 3].all? { |i| i < 3 } => false

#none?

That's right: it's all or nothing.

[1, 2, 3].none? { |i| i.even? } => false

#one?

I've yet to personally find a great use case for this one, but I'm sure it's out there! Performs just like its friends listed above, but this time checking if the condition returns true for only one item. Once two items meet the condition, this method returns false.

[1, 2, 3].one? { |i| i == 2 } => true

If you're dealing with particularly large collections and performance is a concern, you might want to stay away from all? and none? unless you really need them, as they look at every item in the specified collection.

Finding Specific Items

Maybe you already know that there are items in your collection meeting a certain condition. But which items exactly?

#find

This method returns the first item in a collection that meets the condition. find (AKA detect) stops execution once it finds the item, so its impact on program performance is limited.

[1, 2, 3].find { |i| i.odd? } => 1
[1, 2, 3].detect { |i| i.even? } => 2

#find_all

Particularly handy if you need access to every item meeting a condition; find_all (AKA select) will return them all!

[1, 2, 3].find_all { |i| i.odd? } => [1, 3]
[1, 2, 3].select { |i| i.odd? } => [1, 3]

If nothing in the collection returns true for the passed block, both find and find_all will return nil.

Since both of these methods have two different names, which should you use? find and detect will yield the same results, but generally the Ruby community prefers find and find_all over their counterparts--the names are much clearer. When using these monikers, it's significantly easier to tell exactly what a block of code is doing at a glance.

ActiveRecord::OhYeah

Running a Rails app using ActiveRecord? Your ActiveRecord Collections have this module mixed in! Makes for some fun stuff like:

Product.where(color: "Blue").find_all do |product|
  product.current_price < product.original_price
end

if you want to know which blue Products are on sale. You could even do:

User.where.not(email: nil).any? do |user|
  user.email.include? '@apple.com'
end

to see if any of your users work at Apple. Combine any of these Enumerable methods with regular expressions and watch your productivity soar!

Wrapping Up

If you check out Enumerable's documentation, you're sure to see how many stellar and useful methods it includes. So many that they won't all fit in one post! Be on the look out for the next installment of Ruby's Enumerable Module and You, coming soon to a blog near you!