Validar una URL es un trabajo complicado. También es una solicitud muy amplia.
¿Qué quieres hacer exactamente? ¿Quieres validar el formato de la URL, la existencia o qué? Hay varias posibilidades, dependiendo de lo que quieras hacer.
Una expresión regular puede validar el formato de la URL. Pero incluso una expresión regular compleja no puede garantizar que esté tratando con una URL válida.
Por ejemplo, si toma una expresión regular simple, probablemente rechazará el siguiente host
http://invalid##host.com
pero permitirá
http://invalid-host.foo
ese es un host válido, pero no un dominio válido si considera los TLD existentes. De hecho, la solución funcionaría si desea validar el nombre de host, no el dominio porque el siguiente es un nombre de host válido
http://host.foo
así el siguiente
http://localhost
Ahora, déjame darte algunas soluciones.
Si desea validar un dominio, debe olvidarse de las expresiones regulares. La mejor solución disponible en este momento es la Lista de sufijos públicos, una lista mantenida por Mozilla. Creé una biblioteca Ruby para analizar y validar dominios en la lista de sufijos públicos, y se llama PublicSuffix .
Si desea validar el formato de un URI / URL, puede utilizar expresiones regulares. En lugar de buscar uno, use el URI.parse
método Ruby incorporado .
require 'uri'
def valid_url?(uri)
uri = URI.parse(uri) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
Incluso puedes decidir hacerlo más restrictivo. Por ejemplo, si desea que la URL sea una URL HTTP / HTTPS, puede hacer que la validación sea más precisa.
require 'uri'
def valid_url?(url)
uri = URI.parse(url)
uri.is_a?(URI::HTTP) && !uri.host.nil?
rescue URI::InvalidURIError
false
end
Por supuesto, hay toneladas de mejoras que puede aplicar a este método, incluida la comprobación de una ruta o un esquema.
Por último, pero no menos importante, también puede empaquetar este código en un validador:
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