aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/core_ext/range/compare_range.rb
diff options
context:
space:
mode:
authorutilum <oz@utilum.com>2018-05-20 21:22:03 +0200
committerutilum <oz@utilum.com>2018-05-22 14:38:19 +0200
commit0fcb921a65e615c301450d7820b03473acd53898 (patch)
tree8cf5eea647e937b2576d7c5fb058c4e13b6d2dd9 /activesupport/lib/active_support/core_ext/range/compare_range.rb
parent6c574ac58993512f975ddaf1f679c5956cc576df (diff)
downloadrails-0fcb921a65e615c301450d7820b03473acd53898.tar.gz
rails-0fcb921a65e615c301450d7820b03473acd53898.tar.bz2
rails-0fcb921a65e615c301450d7820b03473acd53898.zip
Allow Range#=== and Range#cover? on Range
ruby/ruby@989e07c features switching `Range#===` to use internal `r_cover_p` instead of rubyland `include?`. This breaks expected behavior of `ActiveSupport::CoreExt::Range` documented since at least 8b67a02. This patch adds overrides on `Range#cover?` and `Range#===` and places all three in a single module, `CompareWithRange`. *Requiring core_ext/range/include_range now causes a deprecation warnning*
Diffstat (limited to 'activesupport/lib/active_support/core_ext/range/compare_range.rb')
-rw-r--r--activesupport/lib/active_support/core_ext/range/compare_range.rb61
1 files changed, 61 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/core_ext/range/compare_range.rb b/activesupport/lib/active_support/core_ext/range/compare_range.rb
new file mode 100644
index 0000000000..704041f6de
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/range/compare_range.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module ActiveSupport
+ module CompareWithRange #:nodoc:
+ # Extends the default Range#=== to support range comparisons.
+ # (1..5) === (1..5) # => true
+ # (1..5) === (2..3) # => true
+ # (1..5) === (2..6) # => false
+ #
+ # The native Range#=== behavior is untouched.
+ # ('a'..'f') === ('c') # => true
+ # (5..9) === (11) # => false
+ def ===(value)
+ if value.is_a?(::Range)
+ # 1...10 includes 1..9 but it does not include 1..10.
+ operator = exclude_end? && !value.exclude_end? ? :< : :<=
+ super(value.first) && value.last.send(operator, last)
+ else
+ super
+ end
+ end
+
+ # Extends the default Range#include? to support range comparisons.
+ # (1..5).include?(1..5) # => true
+ # (1..5).include?(2..3) # => true
+ # (1..5).include?(2..6) # => false
+ #
+ # The native Range#include? behavior is untouched.
+ # ('a'..'f').include?('c') # => true
+ # (5..9).include?(11) # => false
+ def include?(value)
+ if value.is_a?(::Range)
+ # 1...10 includes 1..9 but it does not include 1..10.
+ operator = exclude_end? && !value.exclude_end? ? :< : :<=
+ super(value.first) && value.last.send(operator, last)
+ else
+ super
+ end
+ end
+
+ # Extends the default Range#cover? to support range comparisons.
+ # (1..5).cover?(1..5) # => true
+ # (1..5).cover?(2..3) # => true
+ # (1..5).cover?(2..6) # => false
+ #
+ # The native Range#cover? behavior is untouched.
+ # ('a'..'f').cover?('c') # => true
+ # (5..9).cover?(11) # => false
+ def cover?(value)
+ if value.is_a?(::Range)
+ # 1...10 covers 1..9 but it does not cover 1..10.
+ operator = exclude_end? && !value.exclude_end? ? :< : :<=
+ super(value.first) && value.last.send(operator, last)
+ else
+ super
+ end
+ end
+ end
+end
+
+Range.prepend(ActiveSupport::CompareWithRange)