Ranges include? or overlap? with Ranges
Update: This has been added to Rails’ active_support.
The past several days I’ve found myself repeatedly writing the following lines to check if two events are conflicting:
window = course.begin_at...course.end_at
window.include?(event.begin_at) || window.include?(event.end_at?)
It finally donned on me that all I’m really doing is checking if two ranges overlap. What I really wanted to be doing is:
(course.begin_at...course.end_at).overlap?(event.begin_at...event.end_at)
While I was at it, I decided that it only made sense that Range\#include?
should be able to take a range:
class Range
def overlap?(range)
self.include?(range.first) || range.include?(self.first)
end
def include_with_range?(value)
if value.is_a?(Range)
last = value.exclude_end? ? value.last - 1 : value.last
self.include?(value.first) && self.include?(last)
else
include_without_range?(value)
end
end
alias_method_chain :include?, :range
end
update: thanks to Daniel Schierbeck for the better implementation of overlap?
So now, I can do things like:
(1..5).include?(2..3) #=> true
(1..5).include?(4..8) #=> false
(1..5).overlap?(4..8) #=> true
(1...5).overlap?(5..10) #=> false
I love this language!