RubyGuides
Share this post!

7 Little-Known Ruby Methods To Help You Write Better Code

Did you know that using the right Ruby method can save you a lot of work?

The more methods you are familiar with the faster you can produce working code & the better this code will be (both in performance & quality).

That’s why today I want to introduce 7 interesting methods to you that you may not have seen before.

Integer#digits Method (Ruby 2.4)

This is a new method introduced in Ruby 2.4 & it’s very useful if you want to work with the individual digits of an Integer.

Note: In case you are not up to speed on Ruby 2.4 changes, Fixnum & Bignum are now deprecated & both merged into Integer.

You may think that using array-like indexing may work:

2[0]

# 0

2[1]

# 1

But what you get are not the digits, but the binary bits that make up this number.

So pre-digits method the typical solution was to convert the number into a string, then break that string into an array of characters using the chars method, and finally convert every string back into an integer.

Example:

123.to_s.chars.map(&:to_i).reverse

[3, 2, 1]

But in a post-digits method world, you can simply do this:

123.digits

[3, 2, 1]

Much better, isn’t it?

Video:

The Tap Method

Sometimes you want to create an object, call some methods on it & return that same object.

You would have to do something like this:

user = User.new

user.name = "John"

user

The problem is that we have to deal with this temporary variable.

Here’s where the tap method comes to the rescue!

With tap the last example becomes this:

User.new.tap { |user| user.name = "John" }

Notice how the temporary variable is gone, which is a good thing 🙂

Array#values_at

If you want to get multiple non-sequential values from an array or a hash you could do this:

arr = [1,2,3,4,5]

a, b, c = arr[0], arr[1], arr[4]

Or you could use the values_at method:

arr = [1,2,3,4,5]

a, b, c = arr.values_at(0, 1, 4)

This also works with a hash:

hash = {bacon: 300, chocolate: 200}

p hash.values_at(:bacon, :chocolate)

# [300, 200]

Hash#transform_values (Ruby 2.4)

Let’s say you have a hash & want to change all the values for some reason.

Sort of what you would do with Array#map.

The problem with map is that you will get an array-of-arrays (multi-dimensional array) instead of a hash. Also there is no Hash#map!.

So one solution could be this:

h = {bacon: 200, coconut: 300}

h.each { |k,v| h[k] = v*2 }

In this example we multiply each value times two.

Which results in:

{:bacon=>400, :coconut=>600}

Since Ruby 2.4 there is a better way to do this:

h.transform_values! { |v| v * 2 }

This is another of those methods coming from Rails, which is now available outside the framework 🙂

Kernel#itself (Ruby 2.2)

If you told me that this method does not look very interesting at first I would agree with you.

But the reason is that you need to see some good examples.

So let’s say we have an array with repeated words & we want to count them…

While there are many ways to do this, I think this is a great case for testing out our new friend: Kernel#itself.

Example:

words = %w(cat cat tiger dog cat)

words.group_by(&:itself).transform_values(&:size)

Notice how I also combined this with Hash#transform_values!

If transform_values is not available you can do this:

words
  .group_by(&:itself)
  .each_with_object({}) { |(k,v), hash| hash[k] = v.size }

Video:

Note: The itself method shows up under the Object class in the documentation, but the method is defined on the Kernel module.

Array#count

Sometimes you just need to count something.

Instead of using the typical counter + loop you can use the count method!

Example:

letters = %w(a a a b c d a)

letters.count("a")

# 4

The array version of this method also takes a block, so you can do more complex counting.

numbers = [1,2,3,4,5,6]

numbers.count(&:even?)

# 3

Video:

Enumerable#cycle

Do you want to repeat some pattern? Or maybe you need an easy on/off toggle?

Then Enumerable#cycle might be what you are looking for!

Example:

array = %w(a b c)

# Same as array * 3
array.cycle(3).to_a

But my favorite use for cycle is to create a “switch” or “toggle” object.

switch = %w(on off).cycle

switch.next

The nice thing about this is that you don’t need to check the current value of the switch to update it manually.

You can just call next & Ruby will know exactly what to do 🙂

Summary

You have learned about some new useful methods: Integer#digits, Kernel#tap, Array#values_at, Hash#transform_values, Kernel#itself, Array#count, Enumerable#cycle.

If you already knew about these great! If not I hope you find them useful 🙂

Enjoyed this article? Then share it with your friends so they can enjoy it too!

14 comments
Serguei says last year

Thank you sharing, Jesus. There is a typo in Hash#map section: “soultion” instead of “solution”.

    Jesus Castello says last year

    Thanks for reading Serguei! Also thanks for reporting the typo, it’s fixed now 🙂

Ari says last year

That was pretty helpful. I knew couple of methods and have used ’em in the past, but some of ’em really looks interesting. Cant wait to play with ’em. Thank you Jesus!

    Jesus Castello says last year

    I’m glad you found this helpful! Thanks for reading 🙂

Dominic says last year

This is really cool, it’s great to still learn new things about Ruby even after using it for so long.

Jordan says last year

Hey mate,

For what it’s worth, ActiveRecord gives you tap-like functionality out of the box, so where you’ve done:

User.new.tap { |user| user.name = "John" }

The following also works:

User.new { |user| user.name = "John" }

    Jesus Castello says last year

    Thanks for sharing 🙂

    Pedro Coutinho says last year

    Or even:

    User.new(name: ‘john’)

Stefan says last year

You usually want the digits in the same order, so it should be `123.to_s.chars.map(&:to_i)` vs. `123.digits.reverse`.

    Michael Kohl says last year

    The neat thing about the way the digits are arranges is that their array indexes correlated with the power of ten they represent. Or in code:

    “`
    [3,2,1].each_with_index.reduce(0) { |sum, (n, i)| sum + n * 10 ** i }
    #=> 123
    “`

Nick says 11 months ago

I liked that part with the `itself` method! Thanks Jesus!

    Jesus Castello says 11 months ago

    Thanks Nick for reading & leaving a comment 🙂

Vikrant Patel says 11 months ago

Very nicely explained article. Thank you for sharing.

    Jesus Castello says 11 months ago

    Thanks for reading! 🙂

Comments are closed