Ruby: What's the proper syntax for a boolean regex method?
What is the proper synt开发者_如何学运维ax for a method that checks a string for a pattern, and returns true or false if the regex matches?
Basic idea:
def has_regex?(string)
pattern = /something/i
return string =~ pattern
end
Use case:
if has_regex?("something")
# woohoo
else
# nothing found: panic!
end
In the question you said:
... method that checks a string for a pattern, and returns true or false if the regex matches
As johannes pointed out String=~
returns nil
if the pattern did not match and the position in the string where the matched word stared otherwise. Further he states in Ruby everything except nil
and false
behave like true
. All of this is right.
However, they are not exactly true
or false
. Therefore, the last step is to coerce the value to be a Boolean
. This is achieved by wrapping the result in double bangs returns a true
.
def has_regex?(string)
!!(string =~ /something/i)
end
Your code looks fine, but you could write it even smaller.
The return value of String#=~
behaves this way:
nil
if the pattern did not match- the position in the string where the matched word started
In Ruby everything except nil
and false
behaves like true
in a conditional statement so you can just write
if string=~ pattern
# do something
else
# panic
end
To make it return true/false switch the position of pattern and string and use case equality ===
def has_regex?(string)
pattern = /something/i
return pattern === string
end
I absolutely needed it to return true boolean value and digged around. It is actually documented in regexp class http://www.ruby-doc.org/core-2.1.3/Regexp.html#method-i-3D-3D-3D
If you are using Ruby 2.4 or later, there are String#match?(regex)
and Regexp#match?(string)
methods that return booleans without the conversion shenanigans (where needed, usually not), and have improved performance to boot.
https://ruby-doc.org/core-2.4.0/Regexp.html#method-i-match-3F
https://blog.cognitohq.com/new-features-in-ruby-2-4/
For Ruby >= 2.4 or Rails, you can do:
regexp.match?(string)
Adding this to the String class makes it pretty simple to use:
class String
def match?(regex)
!!self.match(regex)
end
end
I added it to Rails initializer (RAILS_ROOT/config/initializers) and you can call directly from the string:
"Something special!".match?(/something/i) #=> true
"Somethin' special!".match?(/something/i) #=> false
For anyone's future reference, double bangs are frowned upon from bbatsov's ruby style guide. Instead of using a double bang, just check if the value isn't nil. If the value isn't nil, it exists.
Instead of doing this:
def has_regex?(string)
!!(string =~ /something/i)
end
You can always do this:
def has_regex?(string)
!(string =~ /something/i).nil?
end
I do not have enough reputation to comment, so I will answer instead.
Use of ===, as suggested by viljar, is advised against in the Ruby Style Guide and will cause Rubocop complaints (under default rules).
I find the most readable way to be:
def match?(string)
!(string =~ /something/i).nil?
end
As I wanted this to work generally, and not just for any specific project, I do not want to modify the environment at all.
I was able to get it to work by simply using the return value from the normal match
method as a conditional. Tested both the positive and negative case on this sample string:
irb(main):014:0> if "123".match(/.2./); puts "worked"; end
worked
=> nil
irb(main):015:0> if "123".match(/.3./); puts "worked"; end
=> nil
If you want the put the pattern in a method, you can just do
def has_my_pattern(st)
st =~ /pattern/
end
Or, perhaps better, put the pattern in a class variable instead?
精彩评论