Skip to content

Commit

Permalink
define Range#match? if Ruby < 2.4
Browse files Browse the repository at this point in the history
See the rationale in the documentation included in this patch.

We are going to gradually introduce this predicate in the code base.
  • Loading branch information
fxn committed Jul 21, 2016
1 parent d4ea18a commit 575dbee
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 2 deletions.
10 changes: 8 additions & 2 deletions activesupport/CHANGELOG.md
@@ -1,3 +1,9 @@
* Defines `Regexp.match?` for Ruby versions prior to 2.4. The predicate
has the same interface, but it does not have the performance boost. It's
purpose is to be able to write 2.4 compatible code.

*Xavier Noria*

* Allow MessageEncryptor to take advantage of authenticated encryption modes.

AEAD modes like `aes-256-gcm` provide both confidentiality and data
Expand Down Expand Up @@ -55,7 +61,7 @@

*John Gesimondo*

* `travel/travel_to` travel time helpers, now raise on nested calls,
* `travel/travel_to` travel time helpers, now raise on nested calls,
as this can lead to confusing time stubbing.

Instead of:
Expand All @@ -69,7 +75,7 @@

preferred way to achieve above is:

travel 2.days do
travel 2.days do
# 2 days from today
end

Expand Down
4 changes: 4 additions & 0 deletions activesupport/lib/active_support/core_ext/regexp.rb
Expand Up @@ -2,4 +2,8 @@ class Regexp #:nodoc:
def multiline?
options & MULTILINE == MULTILINE
end

def match?(string, pos=0)
!! match(string, pos)

This comment has been minimized.

Copy link
@rafaelfranca

rafaelfranca Jul 21, 2016

Member

we usually don't put the space after the !

This comment has been minimized.

Copy link
@fxn

fxn Jul 21, 2016

Author Member

Cools, revised in 21c6f81.

end unless //.respond_to?(:match?)

This comment has been minimized.

Copy link
@spastorino

spastorino Jul 21, 2016

Contributor

Regexp.instance_methods.include?(:match?)

end
24 changes: 24 additions & 0 deletions activesupport/test/core_ext/regexp_ext_test.rb
Expand Up @@ -7,4 +7,28 @@ def test_multiline
assert_equal false, //.multiline?
assert_equal false, /(?m:)/.multiline?
end

# Based on https://github.com/ruby/ruby/blob/trunk/test/ruby/test_regexp.rb.
def test_match_p
/back(...)/ =~ 'backref'
# must match here, but not in a separate method, e.g., assert_send,
# to check if $~ is affected or not.
assert_equal false, //.match?(nil)
assert_equal true, //.match?("")
assert_equal true, /.../.match?(:abc)
assert_raise(TypeError) { /.../.match?(Object.new) }
assert_equal true, /b/.match?('abc')
assert_equal true, /b/.match?('abc', 1)
assert_equal true, /../.match?('abc', 1)
assert_equal true, /../.match?('abc', -2)
assert_equal false, /../.match?("abc", -4)
assert_equal false, /../.match?("abc", 4)
assert_equal true, /\z/.match?("")
assert_equal true, /\z/.match?("abc")
assert_equal true, /R.../.match?("Ruby")
assert_equal false, /R.../.match?("Ruby", 1)
assert_equal false, /P.../.match?("Ruby")
assert_equal 'backref', $&
assert_equal 'ref', $1
end
end
18 changes: 18 additions & 0 deletions guides/source/active_support_core_extensions.md
Expand Up @@ -2916,6 +2916,24 @@ end

NOTE: Defined in `active_support/core_ext/regexp.rb`.

### `match?`

Rails implements `Regexp#match?` for Ruby versions prior to 2.4:

```ruby
/oo/.match?('foo') # => true
/oo/.match?('bar') # => false
/oo/.match?('foo', 1) # => true
```

The backport has the same interface and lack of side-effects in the caller like
not setting `$1` and friends, but it does not have the speed benefits. Its
purpose is to be able to write 2.4 compatible code. Rails itself uses this
predicate internally for example.

Active Support defines `Regexp#match?` only if not present, so code running
under 2.4 or later does run the original one and gets the performance boost.

Extensions to `Range`
---------------------

Expand Down

0 comments on commit 575dbee

Please sign in to comment.