Back to Blog

Ruby 2.7 adds Beginless Range

on August 25, 2020
This blog is part of our Ruby 2.7 series.

Ruby 2.7.0 was released on Dec 25, 2019.

Ruby 2.7 added support for Beginless Range which makes the start of range an optional parameter.

(..100) is a Beginless Range and it is equivalent to (nil..100).

Let's see how Beginless Range could be used.

1> array = (1..10).to_a
2
3# Select first 6 elements
4> array[..5]
5=> [1, 2, 3, 4, 5, 6]
6
7# Select first 5 elements
8> array[...5]
9=> [1, 2, 3, 4, 5]
10
11# grep (INFINITY..5) in (1..5)
12> (1..10).grep(..5)
13=> [1, 2, 3, 4, 5]
14
15# (..100) is equivalent to (nil..100)
16> (..100) == (nil..100)
17=> true

Here is another example where in the case statement the condition can be read as below the specified level.

1case temperature
2when ..-15
3  puts "Deep Freeze"
4when -15..8
5  puts "Refrigerator"
6when 8..15
7  puts "Cold"
8when 15..25
9  puts "Room Temperature"
10when (25..)   # Kindly notice the brackets here
11  puts "Hot"
12end

It can also be used for defining constants for ranges.

1TEMPERATURE = {
2  ..-15  => :deep_freeze,
3  -15..8 => :refrigerator,
4  8..15  => :cold,
5  15..25 => :room_temperature,
6  25..   => :hot
7end

Using Beginless Range in DSL makes it easier to write conditions and it looks more natural.

1
2# In Rails
3User.where(created_at: (..DateTime.now))
4# User Load (2.2ms)  SELECT "users".* FROM "users" WHERE "users"."created_at" <= $1 LIMIT $2  [["created_at", "2020-08-05 15:00:19.111217"], ["LIMIT", 11]]
5
6
7# In RubySpec
8ruby_version(..'1.9') do
9# Tests for old Ruby
10end

Here is the relevant commit and discussion regarding this change.


You might also like

If you liked this blog post, check out similar ones from BigBinary