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.
Contents
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:
[responsive_video type=’youtube’ hide_related=’0′ hide_logo=’0′ hide_controls=’0′ hide_title=’0′ hide_fullscreen=’0′ autoplay=’0′]https://www.youtube.com/watch?v=LFKNhpiOXUU[/responsive_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:
[responsive_video type=’youtube’ hide_related=’0′ hide_logo=’0′ hide_controls=’0′ hide_title=’0′ hide_fullscreen=’0′ autoplay=’0′]https://www.youtube.com/watch?v=2zevygUebeo[/responsive_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:
[responsive_video type=’youtube’ hide_related=’0′ hide_logo=’0′ hide_controls=’0′ hide_title=’0′ hide_fullscreen=’0′ autoplay=’0′]https://www.youtube.com/watch?v=x7kApCyizlo[/responsive_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 🙂
[responsive_video type=’youtube’ hide_related=’0′ hide_logo=’0′ hide_controls=’0′ hide_title=’0′ hide_fullscreen=’0′ autoplay=’0′]https://www.youtube.com/watch?v=jFmveSKn5mA[/responsive_video]
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!
Thank you sharing, Jesus. There is a typo in Hash#map section: “soultion” instead of “solution”.
Thanks for reading Serguei! Also thanks for reporting the typo, it’s fixed now 🙂
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!
I’m glad you found this helpful! Thanks for reading 🙂
This is really cool, it’s great to still learn new things about Ruby even after using it for so long.
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" }
Thanks for sharing 🙂
Or even:
User.new(name: ‘john’)
You usually want the digits in the same order, so it should be `123.to_s.chars.map(&:to_i)` vs. `123.digits.reverse`.
The neat thing about the way the digits are arranged is that their array indexes correlated with the power of ten they represent. Or in code:
I liked that part with the `itself` method! Thanks Jesus!
Thanks Nick for reading & leaving a comment 🙂
Very nicely explained article. Thank you for sharing.
Thanks for reading! 🙂