Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Range#=== and Range#cover? on Range #32938

Merged
merged 2 commits into from
May 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions activesupport/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion activesupport/lib/active_support/core_ext/range.rb
Original file line number Diff line number Diff line change
@@ -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"
61 changes: 61 additions & 0 deletions activesupport/lib/active_support/core_ext/range/compare_range.rb
Original file line number Diff line number Diff line change
@@ -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)
28 changes: 6 additions & 22 deletions activesupport/lib/active_support/core_ext/range/include_range.rb
Original file line number Diff line number Diff line change
@@ -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"
19 changes: 12 additions & 7 deletions guides/source/active_support_core_extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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?`

Expand Down