1. ホーム
  2. ruby-on-rails

[解決済み] Railsです。リンク(URL)を検証する良い方法は何ですか?

2022-05-31 02:07:50

質問

RailsでURLの検証を行う場合、どのようにすればよいのでしょうか。正規表現を使用することを考えていましたが、これがベストプラクティスであるかどうかはわかりません。

また、正規表現を使用する場合、誰かが私に1つを提案できますか? 私はまだRegexに慣れていません。

どのように解決するのですか?

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 ライブラリを作成し、その名前は PublicSuffix .

URI/URLの形式を検証したい場合、正規表現を使うのがよいでしょう。検索する代わりに、Rubyに内蔵されている URI.parse メソッドを使用します。

require 'uri'

def valid_url?(uri)
  uri = URI.parse(uri) && uri.host
rescue URI::InvalidURIError
  false
end

より限定的にすることもできます。例えば、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