Ruby 1.9.2p290 URL正则表达式有时挂起/破坏

时间:2013-04-22 18:08:52

标签: ruby-on-rails ruby regex

我正在使用jQuery validate插件在我的Rails应用程序中进行客户端验证。我还希望在服务器端使用完全相同的正则表达式进行验证,因此我从库中复制了正则表达式并将其设置为我的Customer模型中的常量,该模型的网站属性需要有效的URL。

虽然正则表达式通常有效,但如果我匹配的字符串太长,它会无限期挂起。当我通过Rubular运行它时,我收到以下错误:

Rubular suspects this regex will take forever to parse. Regexes of this sort make Rubular sad. Adjust the regex or else wait a few minutes and try again.

我对正则表达式几乎一无所知,所以我想知道是否有人注意到在Ruby上下文中使用这个正则表达式的任何明显错误。如果Rubular解释了正则表达式的哪一部分引发了警告,那将是非常好的。

class Customer
    URL_REGEX = /^(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i

    validates :website, format: { with: URL_REGEX }, allow_blank: true, length: { maximum: 255 }
end

为了防止正则表达式很难看到,这里有一个链接:https://gist.github.com/mackshkatz/5437179

1 个答案:

答案 0 :(得分:2)

您不需要提供正则表达式。您可以使用URI中的Ruby stdlib中的一个。

只是做:

require 'uri'
class Customer

   validates :website, format: { with: URI::regexp }, allow_blank: true, length: { maximum: 255 }
end

此外,网址必须以httphttps开头。因此,如果字符串不以任何一个开头,您可能需要添加它。