New Features in Ruby 2.5 (with examples)

Arieh Smith
Plated Engineering & Data Science
3 min readMar 15, 2018

--

Photo by ALP STUDIO on Unsplash

Ruby 2.5 is here! We here at Plated like to stay on top of things but unfortunately found the official new feature documentation a little lacking. That’s too bad, because there’s a ton of good stuff in this release. So let’s do a dive into some sweet new features, shall we?

rescue/else/ensure are now allowed to be used directly with do/end blocks

This is huge. One of my biggest pet peeves with Ruby for the longest time is that without a begin, rescue only operates on the method or class level, e.g., you can write:

def bad_method
puts "hi"
raise "this is bad"
puts "will I get run?"
rescue
puts "exception caught"
end

Now, however, rescue/else/ensure work on do…end blocks! So you can do things like:

def method
[1,2,3].each do |num|
num.odd? ? puts "success" : raise "problem"
rescue
puts "no problem!"
end
end

And “no problem” will be outputted thrice.

Object#yield_self

You can call yield_self on any object, pass in the object to a block, and yield the result of the block (unlike tap, which yields the original object). Hence:

3.yield_self { |num| num * 2 } # 6

Use cases might seem few and far between, but it does let you eliminate local variables if you favor a more functional and concise style of programming. Ergo, one could return an array after applying a transformation only if the array meets certain critera:

[1,2,3,4].select(&:even?).yield_self { |arr| arr if arr == [2, 4] }

versus

arr = [1,2,3,4].select(&:even?)
arr if arr == [2, 4]

Hash#transform_keys

Finally a counterpart for Hash#transform_values! You can now do:

{1 => "one", 2 => "two", 3 => "three"}.transform_keys { |k| k * 2 }

And get

{2=>"one", 4=>"two", 6=>"three"}

Hash#slice

This already exists in Rails, but now it’s in Ruby too. Extracts key and value pairs from a hash. Can come in handy:

hash = {1=>2, 3=>4, 5=>6}
hash.slice(1, 3) # {1=>2, 3=>4}

Enumerable#any?, all?, none?, and one? accept a pattern argument

This can be useful in some cases, such as testing whether every instance of an array is a number:

[1,2,3].all?(Numeric) # true

It’s particularly nice with regexes:

["hey", "ho"].all?(/hey/) # false

Struct.new can create classes that accept keyword arguments

Passing in keyword_init: true to Struct.new now makes it accept keyword arguments. I personally don’t run into too many cases where I need to create one-off classes, but it can come in handy occasionally.

Before:

Struct.new(:x,:y, :color).new(1, 2, "red")

After:

Struct.new(:x,:y, :color, keyword_init: true).new(x: 1, y: 2, color: "red")

Thanks for reading everyone! Check out our Careers page if you’re interested in using your Ruby to build amazing software at Plated!

--

--