New Features in Ruby 2.5 (with examples)
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!