我想知道如何在 Rails 中最好地验证 URL。我正在考虑使用正则表达式,但不确定这是否是最佳做法。
而且,如果我要使用正则表达式,有人可以向我推荐一个吗?我还是 Regex 的新手。
最佳答案
验证 URL 是一项棘手的工作。这也是一个非常广泛的要求。
你到底想做什么?你想验证 URL 的格式、存在性还是什么?有多种可能性,具体取决于您想要做什么。
正则表达式可以验证 URL 的格式。但即使是复杂的正则表达式也无法确保您处理的是有效的 URL。
例如,如果你采用一个简单的正则表达式,它可能会拒绝以下主机
http://invalid##host.com
但它会允许
http://invalid-host.foo
如果您考虑现有的 TLD,那是一个有效的主机,但不是一个有效的域。实际上,如果您想验证主机名而不是域,该解决方案将起作用,因为以下是有效的主机名
http://host.foo
还有下面的
http://localhost
现在,让我给你一些解决方案。
如果你想验证一个域,那么你需要忘掉正则表达式。目前可用的最佳解决方案是公共(public)后缀列表,这是一个由 Mozilla 维护的列表。我创建了一个 Ruby 库来根据公共(public)后缀列表解析和验证域,它称为 PublicSuffix .
如果要验证 URI/URL 的格式,则可能需要使用正则表达式。不要搜索一个,而是使用内置的 Ruby URI.parse
方法。
require 'uri'
def valid_url?(uri)
uri = URI.parse(uri) && uri.host
rescue URI::InvalidURIError
false
end
您甚至可以决定对其进行更严格的限制。例如,如果您希望 URL 为 HTTP/HTTPS URL,则可以使验证更加准确。
require 'uri'
def valid_url?(url)
uri = URI.parse(url)
uri.is_a?(URI::HTTP) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
当然,您可以对这种方法进行大量改进,包括检查路径或方案。
最后但同样重要的是,您还可以将此代码打包到验证器中:
class HttpUrlValidator < ActiveModel::EachValidator
def self.compliant?(value)
uri = URI.parse(value)
uri.is_a?(URI::HTTP) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
def validate_each(record, attribute, value)
unless value.present? && self.class.compliant?(value)
record.errors.add(attribute, "is not a valid HTTP URL")
end
end
end
# in the model
validates :example_attribute, http_url: true
关于ruby-on-rails - rails : What's a good way to validate links (URLs)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7167895/