Spec-Zone.ru › Ruby on Rails 4.1

модуль ActiveModel::Validations::ClassMethods

Публичные методы экземпляров

attribute_method?(attribute) Показать исходный код

Возвращает true если attribute является методом атрибута, false в противном случае.

class Person
  include ActiveModel::Validations

  attr_accessor :name
end

User.attribute_method?(:name) # => true
User.attribute_method?(:age)  # => false
# File activemodel/lib/active_model/validations.rb, line 251
def attribute_method?(attribute)
  method_defined?(attribute)
end
clear_validators!() Показать исходный код

Очищает все валидаторы и проверки.

Обратите внимание, что это очистит все, что используется для валидации модели для методов validates_with и validate. Очищаются валидаторы, созданные вызовом validates_with, и колбэки, установленные вызовом validate.

class Person
  include ActiveModel::Validations

  validates_with MyValidator
  validates_with OtherValidator, on: :create
  validates_with StrictValidator, strict: true
  validate :cannot_be_robot

  def cannot_be_robot
    errors.add(:base, 'A person cannot be a robot') if person_is_robot
  end
end

Person.validators
# => [
#      #<MyValidator:0x007fbff403e808 @options={}>,
#      #<OtherValidator:0x007fbff403d930 @options={on: :create}>,
#      #<StrictValidator:0x007fbff3204a30 @options={strict:true}>
#    ]

Если запустить Person.clear_validators!, а затем проверить, какие валидаторы есть у этого класса, получится:

Person.validators # => []

Также будет удалён колбэк, установленный validate :cannot_be_robot, чтобы:

Person._validate_callbacks.empty?  # => true
# File activemodel/lib/active_model/validations.rb, line 215
def clear_validators!
  reset_callbacks(:validate)
  _validators.clear
end
validate(*args, &block) Показать исходный код

Добавляет метод или блок валидации в класс. Это полезно, когда переопределение метода экземпляра validate становится слишком громоздким, и вы ищете более описательное объявление ваших валидаций.

Это можно сделать с помощью символа, указывающего на метод:

class Comment
  include ActiveModel::Validations

  validate :must_be_friends

  def must_be_friends
    errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee)
  end
end

С блоком, который передаётся со текущей записью для валидации:

class Comment
  include ActiveModel::Validations

  validate do |comment|
    comment.must_be_friends
  end

  def must_be_friends
    errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee)
  end
end

Или с блоком, где self указывает на текущую запись для валидации:

class Comment
  include ActiveModel::Validations

  validate do
    errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee)
  end
end

Параметры:

  • :on — Указывает контексты, в которых активна данная валидация. Вы можете передать символ или массив символов. (например, on: :create или on: :custom_validation_context или on: [:create, :custom_validation_context])

  • :if — Указывает метод, процедуру или строку, вызываемую для определения, должна ли произойти валидация (например, if: :allow_validation, или if: Proc.new { |user| user.signup_step > 2 }). Метод, процедура или строка должны возвращать или вычисляться в значение типа true или false.

  • :unless — Указывает метод, процедуру или строку, вызываемую для определения, не должна ли произойти валидация (например, unless: :skip_validation, или unless: Proc.new { |user| user.signup_step <= 2 }). Метод, процедура или строка должны возвращать или вычисляться в значение типа true или false.

# File activemodel/lib/active_model/validations.rb, line 143
def validate(*args, &block)
  options = args.extract_options!
  if options.key?(:on)
    options = options.dup
    options[:if] = Array(options[:if])
    options[:if].unshift lambda { |o|
      Array(options[:on]).include?(o.validation_context)
    }
  end
  args << options
  set_callback(:validate, *args, &block)
end
validates(*attributes) Показать исходный код

Этот метод — сокращение для всех стандартных валидаторов и пользовательских классов валидаторов, оканчивающихся на «Validator». Обратите внимание, что стандартные валидаторы Rails могут быть переопределены внутри конкретных классов путем создания пользовательских классов валидаторов, таких как PresenceValidator.

Примеры использования стандартных валидаторов Rails:

validates :terms, acceptance: true
validates :password, confirmation: true
validates :username, exclusion: { in: %w(admin superuser) }
validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, on: :create }
validates :age, inclusion: { in: 0..9 }
validates :first_name, length: { maximum: 30 }
validates :age, numericality: true
validates :username, presence: true
validates :username, uniqueness: true

Мощность метода validates проявляется при использовании пользовательских валидаторов и стандартных валидаторов в одном вызове для заданного атрибута.

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

class Person
  include ActiveModel::Validations
  attr_accessor :name, :email

  validates :name, presence: true, uniqueness: true, length: { maximum: 100 }
  validates :email, presence: true, email: true
end

Validator классы также могут существовать внутри проверяемого класса, позволяя включать настраиваемые модули валидаторов по мере необходимости.

class Film
  include ActiveModel::Validations

  class TitleValidator < ActiveModel::EachValidator
    def validate_each(record, attribute, value)
      record.errors.add attribute, "must start with 'the'" unless value =~ /\Athe/i
    end
  end

  validates :name, title: true
end

Кроме того, классы валидаторов могут находиться в другом пространстве имён и все равно использоваться в любом классе.

validates :name, :'film/title' => true

Хэш валидаторов также может обрабатывать регулярные выражения, диапазоны, массивы и строки в сокращенной форме.

validates :email, format: /@/
validates :gender, inclusion: %w(male female)
validates :password, length: 6..20

При использовании сокращенной формы диапазоны и массивы передаются инициализатору вашего валидатора в виде options[:in], а другие типы, включая регулярные выражения и строки, передаются в виде options[:with].

Также существует список параметров, которые можно использовать вместе с валидаторами:

  • :on — Указывает, когда активна эта валидация. По умолчанию выполняется во всех контекстах валидации (nil), другие варианты — :create и :update.

  • :if — Указывает метод, процедуру или строку, вызываемую для определения, должна ли произойти валидация (например, if: :allow_validation, или if: Proc.new { |user| user.signup_step > 2 }). Метод, процедура или строка должны возвращать или вычисляться в значение типа true или false.

  • :unless — Указывает метод, процедуру или строку, вызываемую для определения, не должна ли произойти валидация (например, unless: :skip_validation, или unless: Proc.new { |user| user.signup_step <= 2 }). Метод, процедура или строка должны возвращать или вычисляться в значение типа true или false.

  • :allow_nil — Пропустить валидацию, если атрибут nil.

  • :allow_blank — Пропустить валидацию, если атрибут пуст.

  • :strict — Если параметр :strict установлен в true, будет вызвано исключение ActiveModel::StrictValidationFailed вместо добавления ошибки. Параметр :strict также может быть установлен на любое другое исключение.

Пример:

validates :password, presence: true, confirmation: true, if: :password_required?
validates :token, uniqueness: true, strict: TokenGenerationException

Наконец, параметры :if, :unless, :on, :allow_blank, :allow_nil, :strict и :message могут быть заданы для одного конкретного валидатора в виде хэша:

validates :password, presence: { if: :password_required?, message: 'is forgotten.' }, confirmation: true
# File activemodel/lib/active_model/validations/validates.rb, line 102
def validates(*attributes)
  defaults = attributes.extract_options!.dup
  validations = defaults.slice!(*_validates_default_keys)

  raise ArgumentError, "You need to supply at least one attribute" if attributes.empty?
  raise ArgumentError, "You need to supply at least one validation" if validations.empty?

  defaults[:attributes] = attributes

  validations.each do |key, options|
    next unless options
    key = "#{key.to_s.camelize}Validator"

    begin
      validator = key.include?('::') ? key.constantize : const_get(key)
    rescue NameError
      raise ArgumentError, "Unknown validator: '#{key}'"
    end

    validates_with(validator, defaults.merge(_parse_validates_options(options)))
  end
end
validates!(*attributes) Показать исходный код

Этот метод используется для определения валидаций, которые не могут быть исправлены конечными пользователями и считаются исключительными. Таким образом, каждый валидатор, определённый с восклицательным знаком или параметром :strict, установленным в true, всегда будет вызывать ActiveModel::StrictValidationFailed вместо добавления ошибки при неудачной валидации. См. validates для получения дополнительной информации о самой валидации.

class Person
  include ActiveModel::Validations

  attr_accessor :name
  validates! :name, presence: true
end

person = Person.new
person.name = ''
person.valid?
# => ActiveModel::StrictValidationFailed: Name can't be blank
# File activemodel/lib/active_model/validations/validates.rb, line 143
def validates!(*attributes)
  options = attributes.extract_options!
  options[:strict] = true
  validates(*(attributes << options))
end
validates_each(*attr_names, &block) Показать исходный код

Проверяет каждый атрибут по блоку.

class Person
  include ActiveModel::Validations

  attr_accessor :first_name, :last_name

  validates_each :first_name, :last_name, allow_blank: true do |record, attr, value|
    record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z
  end
end

Параметры:

  • :on — Указывает контексты, в которых активна данная валидация. Можно передать символ или массив символов. (например, on: :create или on: :custom_validation_context или on: [:create, :custom_validation_context])

  • :allow_nil — Пропустить валидацию, если атрибут nil.

  • :allow_blank — Пропустить валидацию, если атрибут пуст.

  • :if — Указывает метод, процедуру или строку, вызываемую для определения, должна ли произойти валидация (например, if: :allow_validation, или if: Proc.new { |user| user.signup_step > 2 }). Метод, процедура или строка должны возвращать или вычисляться в значение типа true или false.

  • :unless — Указывает метод, процедуру или строку, вызываемую для определения, не должна ли произойти валидация (например, unless: :skip_validation, или unless: Proc.new { |user| user.signup_step <= 2 }). Метод, процедура или строка должны возвращать или вычисляться в значение типа true или false.

# File activemodel/lib/active_model/validations.rb, line 85
def validates_each(*attr_names, &block)
  validates_with BlockValidator, _merge_attributes(attr_names), &block
end
validates_with(*args, &block) Показать исходный код

Передаёт запись классу или классам, указанным, и позволяет им добавлять ошибки, основанные на более сложных условиях.

class Person
  include ActiveModel::Validations
  validates_with MyValidator
end

class MyValidator < ActiveModel::Validator
  def validate(record)
    if some_complex_logic
      record.errors.add :base, 'This record is invalid'
    end
  end

  private
    def some_complex_logic
      # ...
    end
end

Вы также можете передать ему несколько классов, например:

class Person
  include ActiveModel::Validations
  validates_with MyValidator, MyOtherValidator, on: :create
end

Параметры конфигурации:

  • :on — Указывает, когда активна эта валидация (:create или :update.

  • :if — Указывает метод, процедуру или строку, вызываемую для определения, должна ли произойти валидация (например, if: :allow_validation, или if: Proc.new { |user| user.signup_step > 2 }). Метод, процедура или строка должны возвращать или вычисляться в значение типа true или false.

  • :unless — Указывает метод, процедуру или строку, вызываемую для определения, не должна ли произойти валидация (например, unless: :skip_validation, или unless: Proc.new { |user| user.signup_step <= 2 }). Метод, процедура или строка должны возвращать или вычисляться в значение типа true или false.

  • :strict — Указывает, должна ли валидация быть строгой. См. ActiveModel::Validation#validates! для получения дополнительной информации.

Если вы передадите дополнительные параметры конфигурации, они будут переданы классу и доступны как options:

class Person
  include ActiveModel::Validations
  validates_with MyValidator, my_custom_key: 'my custom value'
end

class MyValidator < ActiveModel::Validator
  def validate(record)
    options[:my_custom_key] # => "my custom value"
  end
end
# File activemodel/lib/active_model/validations/with.rb, line 84
def validates_with(*args, &block)
  options = args.extract_options!
  options[:class] = self

  args.each do |klass|
    validator = klass.new(options, &block)

    if validator.respond_to?(:attributes) && !validator.attributes.empty?
      validator.attributes.each do |attribute|
        _validators[attribute.to_sym] << validator
      end
    else
      _validators[nil] << validator
    end

    validate(validator, options)
  end
end
validators() Показать исходный код

Список всех валидаторов, используемых для проверки модели с помощью метода validates_with.

class Person
  include ActiveModel::Validations

  validates_with MyValidator
  validates_with OtherValidator, on: :create
  validates_with StrictValidator, strict: true
end

Person.validators
# => [
#      #<MyValidator:0x007fbff403e808 @options={}>,
#      #<OtherValidator:0x007fbff403d930 @options={on: :create}>,
#      #<StrictValidator:0x007fbff3204a30 @options={strict:true}>
#    ]
# File activemodel/lib/active_model/validations.rb, line 173
def validators
  _validators.values.flatten.uniq
end
validators_on(*attributes) Показать исходный код

Список всех валидаторов, используемых для проверки конкретного атрибута.

class Person
  include ActiveModel::Validations

  attr_accessor :name , :age

  validates_presence_of :name
  validates_inclusion_of :age, in: 0..99
end

Person.validators_on(:name)
# => [
#       #<ActiveModel::Validations::PresenceValidator:0x007fe604914e60 @attributes=[:name], @options={}>,
#    ]
# File activemodel/lib/active_model/validations.rb, line 235
def validators_on(*attributes)
  attributes.flat_map do |attribute|
    _validators[attribute.to_sym]
  end
end
END_OF_DOCUMENT_MARKER

© 2004–2016 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API