Ruby 3.3 Introduces Range#overlap? method

In Ruby, a Range is an object that represents a range of values with a defined beginning and end. It’s a fundamental data structure used to express a sequence or span between two values, whether they are numeric, alphabetical, or even dates.

We have two ways to define ranges.

# Inclusive Range (includes both start and end values)
inclusive_range = (start_value..end_value)
inclusive_range = (1..5)  # Includes 1, 2, 3, 4, 5
# Exclusive Range (excludes the end value)
exclusive_range = (start_value...end_value)
exclusive_range = (1...5)  # Includes 1, 2, 3, 4 (excludes 5)

Rails Range#overlaps?(range) method

Compare two ranges and see if they overlap each other. overlaps? returns true if two ranges overlap each other otherwise false.

(3..8).overlaps?(8..10) # => true
(2..43).overlaps?(3..5) # => true
(1..5).overlaps?(7..9) # => false

('a'..'z').overlaps?('c'..'d') # => true

(1.day.from_now..5.days.from_now).overlaps?(5.days.from_now..10.days.from_now) # => false
(1.day.from_now.to_date..5.days.from_now.to_date).overlaps?(5.days.from_now.to_date..10.days.from_now.to_date) # => true

(3...8).overlaps?(8...9) # => false
(3...8).overlaps?(7...9) # => true

# works similarly for open ranges.
(3..).overlaps?(...3) # => false

Before Ruby 3.3

Unlike Rails, Ruby does not have any method names as overlap? to compare two ranges and see if they overlap each other.

Prior to Ruby 3.3, if we wanted to check for overlaps. We would need to use the cover method. It would return true if the two ranges overlap each other.

There is a problem with it. It doesn’t work with open ranges.

# Check if range1 covers any value in range2 or vice versa
range1 = (3..8)
range2 = (8..10)
range1.cover?(range2.first) || range2.cover?(range1.first) # => true

range1 = ('a'..'z')
range2 = ('c'..'d')
range1.cover?(range2.first) || range2.cover?(range1.first) # => true

range1 = (1.day.from_now..5.days.from_now)
range2 = (5.days.from_now..10.days.from_now)
range1.cover?(range2.first) || range2.cover?(range1.first) # => false

range1 = (1.day.from_now.to_date..5.days.from_now.to_date)
range2 = (5.days.from_now.to_date..10.days.from_now.to_date)
range1.cover?(range2.first) || range2.cover?(range1.first) # => true

After

Ruby 3.3 introduces Range#overlap?(range) method. Like Rails, we can use overlap? method to compare two ranges and see if they overlap each other.

  • It returns true if two ranges overlap each other otherwise false.
  • It works for open ranges as well.
  • It will raise TypeError, if we don’t pass range.
range1 = (3..8)
range2 = (8..10)
range1.overlap?(range2) # => true

range1 = ('a'..'z')
range2 = ('c'..'d')
range1.overlap?(range2) # => true

range1 = (1.day.from_now..5.days.from_now)
range2 = (5.days.from_now..10.days.from_now)
range1.overlap?(range2) # => false

range1 = (1.day.from_now.to_date..5.days.from_now.to_date)
range2 = (5.days.from_now.to_date..10.days.from_now.to_date)
range1.overlap?(range2) # => true

(3..).overlap?(...3) # => false

(3..8).overlap?(3) # => TypeError, argument must be Range

Need help on your Ruby on Rails or React project?

Join Our Newsletter