Rails で URL を検証する最適な方法を知りたいです。正規表現を使用することを考えていましたが、これがベストプラクティスかどうかはわかりません。
また、正規表現を使用する場合、誰か私に提案してもらえますか? 私はまだ正規表現の初心者です。
ベストアンサー1
URL の検証は難しい作業です。また、非常に広範囲な要求でもあります。
具体的に何をしたいですか? URL の形式、存在、またはその他のものを検証したいですか? 何をしたいかに応じて、いくつかの可能性があります。
正規表現は URL の形式を検証できます。ただし、複雑な正規表現であっても、有効な URL を扱っていることを保証することはできません。
例えば、単純な正規表現を使用すると、次のホストは拒否される可能性があります。
http://invalid##host.com
しかし、それは
http://invalid-host.foo
これは有効なホストですが、既存のTLDを考慮すると有効なドメインではありません。実際、次のものは有効なホスト名であるため、ドメインではなくホスト名を検証したい場合にこの解決策は機能します。
http://host.foo
同様に次のものも
http://localhost
さて、いくつかの解決策をお伝えしましょう。
ドメインを検証したい場合、正規表現は忘れてください。現時点で利用できる最良の解決策は、Mozillaが管理するPublic Suffix Listです。私は、Public Suffix Listに対してドメインを解析および検証するためのRubyライブラリを作成しました。パブリックサフィックス。
URI/URL の形式を検証したい場合は、正規表現を使用することをお勧めします。正規表現を検索する代わりに、組み込みの RubyURI.parse
メソッドを使用します。
require 'uri'
def valid_url?(uri)
uri = URI.parse(uri) && uri.host.present?
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.present?
rescue URI::InvalidURIError
false
end
もちろん、パスやスキームのチェックなど、このメソッドに適用できる改善点は数多くあります。
最後に、このコードをバリデーターにパッケージ化することもできます。
class HttpUrlValidator < ActiveModel::EachValidator
def self.compliant?(value)
uri = URI.parse(value)
uri.is_a?(URI::HTTP) && uri.host.present?
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
新しい URI バージョン (例: 0.12.1) に関する注意
.present?
/ は、以前 (つまり URI v 0.11)または を.blank?
使用する代わりに、ホストを検証するより正確な方法です。uri.host.nil?
if uri.host
URI.parse("https:///394") の例:
- 新しい URI バージョン (0.12) は
host
空の文字列を返し、/394
パスになります。#<URI::HTTPS https:///394> - 古い URI バージョン (0.11) では、
host
空の文字列が返され、/394
パスにもなります。#<URI::HTTPS https:/394>