Rails 3: применить те же правила проверки к нескольким табличным полям

Я создал модель с несколькими полями, которые должны принимать одинаковый формат данных (строки, но могут быть любыми, FWIW). Я хотел бы применить одно и то же правило проверки ко всем этим полям. Конечно, я могу просто пойти и скопировать/вставить материал, но это будет против DRY-принципа и здравого смысла...

Я думаю, что это довольно легко, но я новичок Rails/hipster, поэтому извините-муй за тривиальный вопрос. =)

Ответы

Ответ 1

Итак, если вы сказали три поля для проверки:

:first_name
:last_name
:age

И вы хотели, чтобы все их проверяли? Так что-то вроде этого:

validates_presence_of :first_name, :last_name, :age

Изменить: В Rails существует множество различных методов проверки достоверности), и они великолепно гибки). Для формата поля вы можете использовать validates_format_of, а затем использовать регулярное выражение для сопоставления с ним. Вот пример сопоставления электронной почты:

validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i

Я проверил "Руководство по верификации и обратные вызовы" ; он предоставляет исчерпывающее представление о многих функциях, которые Active Record предоставляет с точки зрения проверки. Вы также можете проверить документацию здесь.

Ответ 2

Если вы используете какую-либо встроенную проверку (наличие, length_of), вы можете применить одну проверку к нескольким атрибутам следующим образом:

validates_presence_of :name, :email

Если у вас есть пользовательская логика, вы можете создать объект-валидатор для размещения кода и применить его индивидуально

class EmailValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors[attribute] << (options[:message] || "is not an email") unless
      value =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
  end
end

def Person
  validates :home_email, :email => true
  validates :work_email, :email => true
end

см. http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/

Ответ 3

В Rails 4 вы можете применить ту же проверку к нескольким столбцам с помощью цикла:

[:beds, :baths].each do |column|
  validates column, allow_blank: true, length: { maximum: 25 }
end

Обе кровати и ванны проверяются с использованием тех же валидаций.

Edit:

В Rails 4.2 вы можете сделать то же самое, поместив несколько символов после вызова функции validates. Пример:

validates :beds, :baths, allow_blank: true

Ответ 4

Используйте Themis для этого:

# Describe common validation in module
module CommonValidation
  extend Themis::Validation

  validates_presence_of :foo
  validates_length_of :bar, :maximum => 255
end

class ModelA < ActiveRecord::Base
  # import validations
  include CommonValidation
end

class ModelB < ActiveRecord::Base
  # import validations
  include CommonValidation
end