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