Memvalidasi URL adalah pekerjaan yang rumit. Ini juga permintaan yang sangat luas.
Sebenarnya apa yang ingin kamu lakukan? Apakah Anda ingin memvalidasi format URL, keberadaannya, atau apa? Ada beberapa kemungkinan, tergantung pada apa yang ingin Anda lakukan.
Ekspresi reguler dapat memvalidasi format URL. Tetapi bahkan ekspresi reguler yang kompleks tidak dapat memastikan Anda berurusan dengan URL yang valid.
Misalnya, jika Anda menggunakan ekspresi reguler sederhana, host berikut mungkin akan ditolak
http://invalid##host.com
tapi itu akan memungkinkan
http://invalid-host.foo
itu adalah host yang valid, tetapi bukan domain yang valid jika Anda mempertimbangkan TLD yang ada. Memang, solusi akan berhasil jika Anda ingin memvalidasi nama host, bukan domainnya karena yang berikut ini adalah nama host yang valid
http://host.foo
serta yang berikut ini
http://localhost
Sekarang, izinkan saya memberi Anda beberapa solusi.
Jika Anda ingin memvalidasi domain, Anda harus melupakan ekspresi reguler. Solusi terbaik yang tersedia saat ini adalah Daftar Sufiks Publik, daftar yang dikelola oleh Mozilla. Saya membuat perpustakaan Ruby untuk mengurai dan memvalidasi domain terhadap Daftar Sufiks Publik, dan itu disebut PublicSuffix .
Jika Anda ingin memvalidasi format URI / URL, Anda mungkin ingin menggunakan ekspresi reguler. Alih-alih mencarinya, gunakan URI.parse
metode Ruby bawaan.
require 'uri'
def valid_url?(uri)
uri = URI.parse(uri) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
Anda bahkan dapat memutuskan untuk membuatnya lebih ketat. Misalnya, jika Anda ingin URL menjadi HTTP / HTTPS URL, Anda dapat membuat validasi lebih akurat.
require 'uri'
def valid_url?(url)
uri = URI.parse(url)
uri.is_a?(URI::HTTP) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
Tentu saja, ada banyak perbaikan yang bisa Anda terapkan pada metode ini, termasuk memeriksa jalur atau skema.
Terakhir, Anda juga dapat mengemas kode ini menjadi validator:
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