开发者

What is a Ruby regex to match a function name? [duplicate]

This question already has answers here: What are the restrictions for method names in Ruby? 开发者_运维知识库 (5 answers) Closed 7 years ago.

Our app uses the send method to call functions on our objects. Unfortunately, some times the string passed to send may not be a legit method name in Ruby. Does anyone know of a regexp that would allow us to check this?

And by legit, I mean a method name that doesn't start with "?", etc. I don't care whether the object responds to the method, because we use method_missing in this case, and we actually want it to be used, which would only happen for methods for which the object doesn't respond.

Technically, I'm looking for a regexp which does this :

Ruby identifiers are consist of alphabets, decimal digits, and the underscore character, and begin with a alphabets(including underscore). There are no restrictions on the lengths of Ruby identifiers.


You can take advantage of the fact that Symbol#inspect quotes the name when it is not a valid identifier. A valid symbol becomes ":hello!" when inspected, but an invalid one becomes ":\"invalid!?\"". This handles exotic symbols like :foo=, :[]=, and any other valid method name.

Adding the additional requirement that @-names are valid identifiers but not valid method names gives us this:

class Symbol
  def method_name?
    return /[@$"]/ !~ inspect
  end
end


What if it is a legit method name, but the method doesn't actually exist on the object you're attempting to send it to?

Either way, you should check that the object responds to a method before attempting to invoke it, no matter if the string is a legit method name of not. You can do this by using the Object#respond_to? method.

For example:

obj = Person.new
method = "set_name"

if obj.respond_to?(method)
  obj.send(method, "foo")
end

If you want to make sure a string is a legit method name you'd want to use regular expressions.. something like /^([a-zA-Z_]+|\[\])[\?!=]?$/ should work for general methods. Regardless my point still stands for making sure this object responds to a method name


Ruby method identifiers allowed in source code can be matched by this:

# Yes, upper-case first letters are legal
/\A(?:[a-z_]\w*[?!=]?|\[\]=?|<<|>>|\*\*|[!~+\*\/%&^|-]|[<>]=?|<=>|={2,3}|![=~]|=~)\z/i 

However, note that methods may be defined that don't match this pattern:

class Foo
  define_method("!dumb~name"){ puts "yup" }
 end
 Foo.new.send('!dumb~name')
 #=> yup

Edit: Updated to add all the Operator Expressions.


I'm not so sure regexp is the way to go here but here's a try

def could_be_method_name?(m)
   match = /^([a-zA-Z_]([\w]*[\w!?=]$){0,1})/.match(m)
   return match == nil ? false : match[1].length==m.length
end

Ruby method names must start with a letter or an underscore. They can only contain alphanumeric characters but the last character is allowed to also be !, ?, or =.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜