Spec-Zone.ru › Ruby on Rails 7.2

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

Общедоступные методы экземпляров

attribute_method?(attribute) Показать исходный код
# File activemodel/lib/active_model/validations.rb, line 284
def attribute_method?(attribute)
  method_defined?(attribute)
end

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

class Person
  include ActiveModel::Validations

  attr_accessor :name
end

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

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

Обратите внимание, что это очистит всё, что используется для проверки модели для методов 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
validate(*args, &block) Показать исходный код
# File activemodel/lib/active_model/validations.rb, line 171
def validate(*args, &block)
  options = args.extract_options!

  if args.all?(Symbol)
    options.each_key do |k|
      unless VALID_OPTIONS_FOR_VALIDATE.include?(k)
        raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{VALID_OPTIONS_FOR_VALIDATE.map(&:inspect).join(', ')}. Perhaps you meant to call `validates` instead of `validate`?")
      end
    end
  end

  if options.key?(:on)
    options = options.merge(if: [predicate_for_validation_context(options[:on]), *options[:if]])
  end

  set_callback(:validate, *args, options, &block)
end

Добавляет метод или блок валидации к классу. Это полезно, когда переопределение метода экземпляра 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

Обратите внимание, что возвращаемое значение методов валидации не имеет значения. Остановка цепочки обратных вызовов validate невозможна.

Параметры:

  • :on — Указывает контексты, в которых эта проверка активна. По умолчанию выполняется во всех контекстах проверки nil. Вы можете передать символ или массив символов. (например, 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.

ПРИМЕЧАНИЕ: Вызов validate несколько раз для одного и того же метода перезапишет предыдущие определения.

validates(*attributes) Показать исходный код
# File activemodel/lib/active_model/validations/validates.rb, line 106
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|
    key = "#{key.to_s.camelize}Validator"

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

    next unless options

    validates_with(validator, defaults.merge(_parse_validates_options(options)))
  end
end

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

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

validates :username, absence: true
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 проявляется при использовании пользовательских и стандартных валидаторов в одном вызове для заданного атрибута.

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

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

  validates :name, presence: 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 /\Athe/i.match?(value)
    end
  end

  validates :name, title: true
end

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

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

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

validates :email, format: /@/
validates :role, inclusion: %w(admin contributor)
validates :password, length: 6..20

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

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

  • :on — Указывает контексты, в которых эта проверка активна. По умолчанию выполняется во всех контекстах проверки nil. Вы можете передать символ или массив символов. (например, 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.

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

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

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

Пример:

validates :password, presence: true, confirmation: true, if: :password_required?
validates :token, length: { is: 24 }, strict: TokenLengthException

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

validates :password, presence: { if: :password_required?, message: 'is forgotten.' }, confirmation: true
validates!(*attributes) Показать исходный код
# File activemodel/lib/active_model/validations/validates.rb, line 148
def validates!(*attributes)
  options = attributes.extract_options!
  options[:strict] = true
  validates(*(attributes << options))
end

Этот метод используется для определения валидаций, которые не могут быть исправлены конечными пользователями и считаются исключительными. Так каждый валидатор, определённый с восклицательным знаком или с параметром :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
validates_each(*attr_names, &block) Показать исходный код
# File activemodel/lib/active_model/validations.rb, line 104
def validates_each(*attr_names, &block)
  validates_with BlockValidator, _merge_attributes(attr_names), &block
end

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

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.start_with?("z")
  end
end

Параметры:

  • :on — Указывает контексты, в которых эта проверка активна. По умолчанию выполняется во всех контекстах проверки nil. Вы можете передать символ или массив символов. (например, 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.

validates_with(*args, &block) Показать исходный код
# File activemodel/lib/active_model/validations/with.rb, line 88
def validates_with(*args, &block)
  options = args.extract_options!
  options[:class] = self

  args.each do |klass|
    validator = klass.new(options.dup, &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

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

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

Для validates_with нет сообщения об ошибке по умолчанию. Вы должны вручную добавить ошибки в коллекцию ошибок записи в классе валидатора.

Для реализации метода validate необходимо определить параметр record, который представляет собой проверяемую запись.

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

  • :on — Указывает контексты, в которых активна эта проверка. По умолчанию работает во всех контекстах проверки nil. Вы можете передать символ или массив символов. (например, 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.

  • :strict — Указывает, должна ли проверка быть строгой. Дополнительная информация в ActiveModel::Validations#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
validators() Показать исходный код
# File activemodel/lib/active_model/validations.rb, line 206
def validators
  _validators.values.flatten.uniq
end

Список всех валидаторов, используемых для проверки модели с помощью метода 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}>
#    ]
validators_on(*attributes) Показать исходный код
# File activemodel/lib/active_model/validations.rb, line 268
def validators_on(*attributes)
  attributes.flat_map do |attribute|
    _validators[attribute.to_sym]
  end
end

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

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={}>,
#    ]

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

Spec-Zone.ru

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