Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Ruby: про email вообще и ради валидации без регекспов, в частности

Anna | 20.06.2014 | нет комментариев
По предложенному вопросу пергамента исписано непозволительно много. Тем не менее я бы хотел остановится на 3 значимых но игнорируемых аттрибутах присущных email-у с точки web-разработки.
Во первых email уникален, в различии от никнейма тот, что в половине случаев занят кем-то до нас, впрочем все еще встречаются сайты с логином по никнейму, тот, что для всех таких сайтов никак не упомнить. Предлагаю применять для логина только email.
Во вторых, часть разработчиков игнорирует type=’email’, когда JS валидаторы нантравлены на это поле, и планшетные устройства переключают раскладку, что комфортно.
В третьих, ради чего это статья, всякий год пишутся статьи вида «Отчего нехорошо валидировать регекспом», что огромнее схоже на фетишь. Верю гугл проиндексирует правильно.Собственно каждая преамбула ради одного увлекательного решения, которое должно подмогнуть Ruby-стам, не исключено, что в других языках сходственный способ тоже реализуем.

Собственно когда задача 1-й раз сформулировалась в моей голове как задача, то я воспользовался гуглом, и в два три клика наткнулся на решение, которым пользуюсь до сих пор. Значимо: решение бесстыдно стырено и выдается за свое, и если кто-то обнаружит ссылку на первоисточник, с радостью вставлю в статью.

Первй показатель валидности

gem ‘mail’ старинная как мир рубишная библиотека

require 'mail'
mail = Mail::Addres.new('antiqe@gmail.com')
mail.local #antiqe
mail.domain #gmail.com

Это первое что необходимо сделать
Если в адресе почты содержатся недопустимые символы, то библиотека вызовет exception тот, что необходимо поймать. Впрочем, нам ничего не ясно про домен, и домен здесь может быть инвалидным.

2-й показатель валидности

mail = Mail::Address.new('antiqe@gmail.com')
 => #<Mail::Address:72490440 Address: |antiqe@gmail.com| > 

tree = mail.__send__(:tree)
 => SyntaxNode Address1 AddrSpec0 offset=0, "antiqe@gmail.com" (dig_comments,comments,local_part,domain):
  SyntaxNode LocalDotAtom0 offset=0, "antiqe" (local_dot_atom_text):
    SyntaxNode CFWS1 offset=0, "":
      SyntaxNode offset=0, ""
      SyntaxNode offset=0, ""
    SyntaxNode offset=0, "antiqe":
      SyntaxNode LocalDotAtomText0 offset=0, "antiqe" (domain_text):
        SyntaxNode offset=0, ""
        SyntaxNode offset=0, "antiqe":
          SyntaxNode offset=0, "a"
          SyntaxNode offset=1, "n"
          SyntaxNode offset=2, "t"
          SyntaxNode offset=3, "i"
          SyntaxNode offset=4, "q"
          SyntaxNode offset=5, "e"
    SyntaxNode CFWS1 offset=6, "":
      SyntaxNode offset=6, ""
      SyntaxNode offset=6, ""
  SyntaxNode offset=6, "@"
  SyntaxNode DotAtom0 offset=7, "gmail.com" (dot_atom_text):
    SyntaxNode CFWS1 offset=7, "":
      SyntaxNode offset=7, ""
      SyntaxNode offset=7, ""
    SyntaxNode offset=7, "gmail.com":
      SyntaxNode DotAtomText0 offset=7, "gmail." (domain_text):
        SyntaxNode offset=7, "gmail":
          SyntaxNode offset=7, "g"
          SyntaxNode offset=8, "m"
          SyntaxNode offset=9, "a"
          SyntaxNode offset=10, "i"
          SyntaxNode offset=11, "l"
        SyntaxNode offset=12, "."
      SyntaxNode DotAtomText0 offset=13, "com" (domain_text):
        SyntaxNode offset=13, "com":
          SyntaxNode offset=13, "c"
          SyntaxNode offset=14, "o"
          SyntaxNode offset=15, "m"
        SyntaxNode offset=16, ""
    SyntaxNode CFWS1 offset=16, "":
      SyntaxNode offset=16, ""
      SyntaxNode offset=16, "" 

У нас здесь синтаксическое дерево, природа и свойства которого для меня чуть менее чем всецело непостижимы. Знаю только то, что синтаксическое дерево в различии от регекспа не рекурсивно по своей природе.
Дозволено только предположить, что создатели библиотеки, что-то знали, но сказали не каждому.
Это дерево дает нам вероятность сделать один значимый итог: из скольких элементов состоит домен. И если таких элементов больше одно — домен валиден.

Частная реализация

В рельсах довольно вот это:


require 'mail'
class EmailValidator < ActiveModel::EachValidator
  def validate_each(record,attribute,value)
    begin
      address = Mail::Address.new(value)
      result = address.domain && address.address == value # правда, что то что распарсил Mail в сумме вернет нам обратно наш email
      tree = address.__send__(:tree)
      result &&= (tree.domain.dot_atom_text.elements.size > 1) # правда ли и то, что елементов в домене огромнее одного
    rescue Exception => e # ловим  исключение, если в адресе русские либо китайские символы
      result = false
    end
    record.errors[attribute] << (options[:message] || "is invalid") unless result
  end
end

положить в app/validators/email_validator.rb, Дабы в всякий модели применять:

validates :email, :presence => true, :email => true

Ложноинвалидных либо ложноположительных адресов за больше чем два года не выявлено.
Огромнее сказать нечего.
Каждому добродушна.

 

Источник: programmingmaster.ru

 

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB