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!