开发者

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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜