Ruby 2.7 adds Beginless Range

Ashwath Biradar

By Ashwath Biradar

on August 25, 2020

This blog is part of our  Ruby 2.7 series.

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.

Stay up to date with our blogs. Sign up for our newsletter.

We write about Ruby on Rails, ReactJS, React Native, remote work,open source, engineering & design.