Ruby 2.7 adds Beginless Range

Ashwath Biradar

Ashwath Biradar

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.

> array = (1..10).to_a

# Select first 6 elements
> array[..5]
=> [1, 2, 3, 4, 5, 6]

# Select first 5 elements
> array[...5]
=> [1, 2, 3, 4, 5]

# grep (INFINITY..5) in (1..5)
> (1..10).grep(..5)
=> [1, 2, 3, 4, 5]

# (..100) is equivalent to (nil..100)
> (..100) == (nil..100)
=> true

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

case temperature
when ..-15
  puts "Deep Freeze"
when -15..8
  puts "Refrigerator"
when 8..15
  puts "Cold"
when 15..25
  puts "Room Temperature"
when (25..)   # Kindly notice the brackets here
  puts "Hot"
end

It can also be used for defining constants for ranges.

TEMPERATURE = {
  ..-15  => :deep_freeze,
  -15..8 => :refrigerator,
  8..15  => :cold,
  15..25 => :room_temperature,
  25..   => :hot
end

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


# In Rails
User.where(created_at: (..DateTime.now))
# 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]]


# In RubySpec
ruby_version(..'1.9') do
# Tests for old Ruby
end

Here is the relevant commit and discussion regarding this change.

If this blog was helpful, check out our full blog archive.

Stay up to date with our blogs.

Subscribe to receive email notifications for new blog posts.