diff options
-rw-r--r-- | activesupport/CHANGELOG.md | 11 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/range.rb | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/range/compare_range.rb | 61 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/range/include_range.rb | 28 | ||||
-rw-r--r-- | guides/source/active_support_core_extensions.md | 19 |
5 files changed, 91 insertions, 30 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index a384fc3bd2..91818c3112 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,14 @@ +* Allow Range#=== and Range#cover? on Range + + `Range#cover?` can now accept a range argument like `Range#include?` and + `Range#===`. `Range#===` works correctly on Ruby 2.6. `Range#include?` is moved + into a new file, with these two methods. + + *Requiring active_support/core_ext/range/include_range is now deprecated.* + *Use `require "active_support/core_ext/range/compare_range"` instead.* + + *utilum* + * Add `index_with` to Enumerable. Allows creating a hash from an enumerable with the value from a passed block diff --git a/activesupport/lib/active_support/core_ext/range.rb b/activesupport/lib/active_support/core_ext/range.rb index 4074e91d17..78814fd189 100644 --- a/activesupport/lib/active_support/core_ext/range.rb +++ b/activesupport/lib/active_support/core_ext/range.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require "active_support/core_ext/range/conversions" -require "active_support/core_ext/range/include_range" +require "active_support/core_ext/range/compare_range" require "active_support/core_ext/range/include_time_with_zone" require "active_support/core_ext/range/overlaps" require "active_support/core_ext/range/each" 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) diff --git a/activesupport/lib/active_support/core_ext/range/include_range.rb b/activesupport/lib/active_support/core_ext/range/include_range.rb index 7ba1011921..2da2c587a3 100644 --- a/activesupport/lib/active_support/core_ext/range/include_range.rb +++ b/activesupport/lib/active_support/core_ext/range/include_range.rb @@ -1,25 +1,9 @@ # frozen_string_literal: true -module ActiveSupport - module IncludeWithRange #:nodoc: - # 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 - end -end +require "active_support/deprecation" -Range.prepend(ActiveSupport::IncludeWithRange) +ActiveSupport::Deprecation.warn "You have required `active_support/core_ext/range/include_range`. " \ +"This file will be removed in Rails 6.1. You should require `active_support/core_ext/range/compare_range` " \ + "instead." + +require "active_support/core_ext/range/compare_range" diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md index cde217e1e4..057651e0cf 100644 --- a/guides/source/active_support_core_extensions.md +++ b/guides/source/active_support_core_extensions.md @@ -2889,9 +2889,9 @@ As the example depicts, the `:db` format generates a `BETWEEN` SQL clause. That NOTE: Defined in `active_support/core_ext/range/conversions.rb`. -### `include?` +### `===`, `include?`, and `cover?` -The methods `Range#include?` and `Range#===` say whether some value falls between the ends of a given instance: +The methods `Range#===`, `Range#include?`, and `Range#cover?` say whether some value falls between the ends of a given instance: ```ruby (2..3).include?(Math::E) # => true @@ -2900,18 +2900,23 @@ The methods `Range#include?` and `Range#===` say whether some value falls betwee Active Support extends these methods so that the argument may be another range in turn. In that case we test whether the ends of the argument range belong to the receiver themselves: ```ruby +(1..10) === (3..7) # => true +(1..10) === (0..7) # => false +(1..10) === (3..11) # => false +(1...9) === (3..9) # => false + (1..10).include?(3..7) # => true (1..10).include?(0..7) # => false (1..10).include?(3..11) # => false (1...9).include?(3..9) # => false -(1..10) === (3..7) # => true -(1..10) === (0..7) # => false -(1..10) === (3..11) # => false -(1...9) === (3..9) # => false +(1..10).cover?(3..7) # => true +(1..10).cover?(0..7) # => false +(1..10).cover?(3..11) # => false +(1...9).cover?(3..9) # => false ``` -NOTE: Defined in `active_support/core_ext/range/include_range.rb`. +NOTE: Defined in `active_support/core_ext/range/compare_range.rb`. ### `overlaps?` |