Ruby 3.3 introduces range overlap? method
Rails has a built-in method called #overlaps?
that allows you to compare two ranges
to see if they overlap each other.
This method needed to be included in Ruby.
A range is a data type that represents a sequence of values.
A sequence can be any data type,
including numbers,
characters
and
dates.
A range is represented using the ..
and
...
operators.
// .. operator
(1..5).overlaps?(4..6)
=> true
(1..5).overlaps?(5..8)
=> true
(1..5).overlaps?(-3..0)
=> false
('a'..'z').overlaps?('c')
=> true
(Time.now..(Time.now + 5.days)).overlaps?((Time.now + 2.days)..(Time.now + 6.days))
=> true
// ... operator
(1...5).overlaps?(4...6)
=> true
(1...5).overlaps?(5...8)
=> false
(1...5).overlaps?(-1...1)
=> false
Before Ruby 3.3
To evaluate if two ranges overlap,
you need to use the cover?
method.
Let's say you have two ranges,
a = (1..5)
and
b = (5..10)
,
you can check if they overlap by using the cover?
function
as below:
a.eql?(b) || a.cover?(b.first) || b.cover?(a.first)
=> true
b.first
returns the first value 5
of the range b
.
a.cover?(b.first)
verifies if the value 5
is present in the range a
.
The result will be false if you modify the range
b
to (89..120)
.
a.eql?(b) || a.cover?(b.first) || b.cover?(a.first)
=> false
In Ruby 3.3
With Ruby 3.3,
you can use the overlap?
method instead of the eql?
and
cover?
methods.
a = (1..5)
b = (5..10)
a.overlap?(b)
=> true
a = (1..5)
b = (89..120)
a.overlap?(b)
=> false
The overlap?
method works similarly for open ranges.
(1..).overlap?(...1)
=> false
(...1).overlap?(1..)
=> false
(..1).overlap?(1...)
=> true
If you pass a non-range value as a parameter to the overlap?
method,
it will raise TypeError.
(1..5).overlap?(1)
=> TypeError, argument must be Range
(1..5).overlap?(nil)
=> TypeError, argument must be Range
To know more about this feature, please refer to this PR.