модуль ActiveModel::Validations::ClassMethods
Публичные методы экземпляров
Возвращает 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
Очищает все валидаторы и проверки.
Обратите внимание, что это очистит все, что используется для валидации модели для методов 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 становится слишком громоздким, и вы ищете более описательное объявление ваших валидаций.
Это можно сделать с помощью символа, указывающего на метод:
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 Этот метод — сокращение для всех стандартных валидаторов и пользовательских классов валидаторов, оканчивающихся на «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 Этот метод используется для определения валидаций, которые не могут быть исправлены конечными пользователями и считаются исключительными. Таким образом, каждый валидатор, определённый с восклицательным знаком или параметром :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
Проверяет каждый атрибут по блоку.
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
Передаёт запись классу или классам, указанным, и позволяет им добавлять ошибки, основанные на более сложных условиях.
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 Список всех валидаторов, используемых для проверки модели с помощью метода 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
Список всех валидаторов, используемых для проверки конкретного атрибута.
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
© 2004–2016 David Heinemeier Hansson
Licensed under the MIT License.