регулярные выражения и рельсы валидации - PullRequest
0 голосов
/ 15 февраля 2020

У меня есть две таможенные проверки:

  def validate_email
    regexp = "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+"
    if sleep_email.present? && !sleep_email.match(regexp)
      errors.add(:sleep_email, "l'email indiqué semble ne pas avoir le bon format")
    end
  end

  def validate_website
    regexp = "(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?"
    if website.present? && !website.match(regexp)
      errors.add(:website, "l'url de votre site web doit avoir la forme de http://votresite.com")
    end
  end

Но yo@yo и http://website являются действительными. Что не так ?

Ответы [ 2 ]

2 голосов
/ 15 февраля 2020

Вы строите регулярные выражения, используя строки. Строки и регулярные выражения имеют различное цитирование. Вы фактически дважды убегаете. Такие вещи, как \. превращаются в простые ..

# This results in the regex /a.c/
p "abc".match?("a\.c")  # true

# This results in the desired regex /a\.c/
p "abc".match?("a\\.c")  # true

# This avoids the string escaping entirely.
p "abc".match?(%r{a\.c})  # false

Чтобы избежать этого двойного побега, используйте /.../ или %r{...} для создания регулярных выражений.


Не пытайтесь проверить электронную почту с помощью регулярного выражения. Вместо этого используйте validates_email_format_of gem , который обеспечивает правильный валидатор, который вы можете использовать для любого атрибута.

validates :sleep_email, presence: true, email_format: true

Если вы хотите увидеть, как полностью проверить адрес электронной почты, посмотрите на источник .


Регулярное выражение вашего URL работает.

regexp = "(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?"
p "http://website".match?(regexp)  # true

http://website - допустимый синтаксис URL. Проверка правильности хоста не в работе URL.

Если вы также хотите проверить части URL, ваше регулярное выражение будет становиться все более сложным. Вместо этого проанализируйте URL-адрес с помощью URI, а затем проверьте его отдельные части, как вам нравится.

Вот пользовательский валидатор , который я выбрал, который анализирует URI, проверяет это разрешенная схема, и она выполняет очень элементарную проверку на хосте.

class UrlValidator < ActiveModel::EachValidator
  ALLOWED_SCHEMES = ['http', 'https']

  private def allowed_schemes
    options[:allowed_schemes] || ALLOWED_SCHEMES
  end

  def validates_each(record, attribute, value)
    uri = URI(value)

    if !allowed_schemes.include?(uri.scheme)
      record.errors.add(attribute, :scheme_not_allowed, message: "Scheme #{uri.scheme} is not allowed")
    end

    # Has to have at least xxx.yyy
    # This is a pretty sloppy host check.
    if !uri.host.match?(/\w+\.\w+/)
      record.errors.add(attribute, :host_not_allowed, message: "Host #{uri.host} is not allowed")
    end
  rescue URI::Error
    record.errors.add(attribute, :not_a_uri)
  end
end
validates :website, url: true

Если вы хотите разрешить другие схемы, например ftp ...

validates :website, url: { allowed_schemes: ['http', 'https', 'ftp'] }

Если вам нужна истинная проверка домена, вы можете добавить поиск DNS.

  begin
    Resolv::DNS.open do |dns|
      dns.getaddress(uri.host) }
    end
  rescue Resolv::ResolvError
    record.errors.add(attribute, :invalid_host, { message: "#{uri.host} could not be resolved" }
  end

Однако этот поиск влияет на производительность.

1 голос
/ 15 февраля 2020

Стандартное регулярное выражение электронной почты (RF C 5322 Официальный стандарт) для использования:

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

Что касается URL веб-сайта, используйте его. URL будет действителен только в том случае, если включен TLD (.com,. net, et c.).

^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...