Rails: リンク (URL) を検証する良い方法は何ですか?

概要

Rails で URL を検証する最善の方法は何かと考えていました。正規表現を使用することを考えていましたが、これがベストプラクティスかどうかわかりません。

また、正規表現を使用する場合、誰かが正規表現を提案してもらえますか?私はまだ正規表現を使い始めたばかりです。

解決策

URL の検証は難しい作業です。それは非常に幅広い要求でもあります。

具体的に何がしたいのですか? URL の形式、存在、またはその他を検証しますか?やりたいことに応じて、いくつかの可能性があります。

正規表現を使用して URL の形式を検証できます。ただし、複雑な正規表現であっても、有効な URL を扱っていることを保証することはできません。

たとえば、単純な正規表現を使用すると、次のホストが拒否される可能性があります。

http://invalid##host.com

しかしそれは許可します

http://invalid-host.foo

これは有効なホストですが、既存の TLD を考慮すると有効なドメインではありません。実際、次のホスト名は有効なホスト名であるため、ドメインではなくホスト名を検証したい場合、この解決策は機能します。

http://host.foo

次のものも同様に

http://localhost

さて、いくつかの解決策を紹介します。

ドメインを検証する場合は、正規表現を忘れる必要があります。現時点で利用可能な最良のソリューションは、Mozilla が管理するリストであるパブリック サフィックス リストです。私はパブリック サフィックス リストに対してドメインを解析して検証するための Ruby ライブラリを作成しました。これは PublicSuffix と呼ばれます。

URI/URL の形式を検証する場合は、正規表現を使用することをお勧めします。検索する代わりに、組み込みの Ruby URI.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.host.nil を使用する代わりに、ホストを検証するより正確な方法はありますか?または、uri.host が以前の場合 (つまり、URI v 0.11)。

URI.parse(“https:///394”) の例: