class ActiveModel::Errors
Active Model Ошибки
Предоставляет функциональность, связанную с ошибками, которую можно включить в ваш объект для обработки сообщений об ошибках и взаимодействия с помощниками Action View.
Минимальная реализация может быть такой:
class Person
# Required dependency for ActiveModel::Errors
extend ActiveModel::Naming
def initialize
@errors = ActiveModel::Errors.new(self)
end
attr_accessor :name
attr_reader :errors
def validate!
errors.add(:name, :blank, message: "cannot be nil") if name.nil?
end
# The following methods are needed to be minimally implemented
def read_attribute_for_validation(attr)
send(attr)
end
def self.human_attribute_name(attr, options = {})
attr
end
def self.lookup_ancestors
[self]
end
end
Последние три метода необходимы в вашем объекте, чтобы Errors корректно генерировать сообщения об ошибках, а также обрабатывать несколько языков. Конечно, если вы расширяете свой объект с помощью ActiveModel::Translation, вам не нужно реализовывать последние два. Аналогично, использование ActiveModel::Validations обработает для вас методы, связанные с валидацией.
Вышеприведённое позволяет вам сделать следующее:
person = Person.new person.validate! # => ["cannot be nil"] person.errors.full_messages # => ["name cannot be nil"] # etc..
Атрибуты
Фактический массив объектов Error. Этот метод является псевдонимом для objects.
Фактический массив объектов Error. Этот метод является псевдонимом для objects.
Публичные методы класса
# File activemodel/lib/active_model/errors.rb, line 117 def initialize(base) @base = base @errors = [] end
Передайте экземпляр объекта, использующего объект ошибок.
class Person
def initialize
@errors = ActiveModel::Errors.new(self)
end
end
Общедоступные методы экземпляров
# File activemodel/lib/active_model/errors.rb, line 229 def [](attribute) messages_for(attribute) end
При передаче символа или имени метода возвращает массив ошибок для метода.
person.errors[:name] # => ["cannot be nil"] person.errors['name'] # => ["cannot be nil"]
# File activemodel/lib/active_model/errors.rb, line 342
def add(attribute, type = :invalid, **options)
attribute, type, options = normalize_arguments(attribute, type, **options)
error = Error.new(@base, attribute, type, **options)
if exception = options[:strict]
exception = ActiveModel::StrictValidationFailed if exception == true
raise exception, error.full_message
end
@errors.append(error)
error
end Добавляет новую ошибку type для attribute. Можно добавить несколько ошибок к одному и тому же attribute. Если тип type не указан, используется :invalid.
person.errors.add(:name)
# Adds <#ActiveModel::Error attribute=name, type=invalid>
person.errors.add(:name, :not_implemented, message: "must be implemented")
# Adds <#ActiveModel::Error attribute=name, type=not_implemented,
options={:message=>"must be implemented"}>
person.errors.messages
# => {:name=>["is invalid", "must be implemented"]}
Если type — строка, она используется в качестве сообщения об ошибке.
Если type — символ, он переводится с использованием соответствующего контекста (см. generate_message).
person.errors.add(:name, :blank)
person.errors.messages
# => {:name=>["can't be blank"]}
person.errors.add(:name, :too_long, count: 25)
person.errors.messages
# => ["is too long (maximum is 25 characters)"]
Если type — процедура, она вызывается, что позволяет использовать такие вещи, как Time.now внутри ошибки.
Если параметр :strict установлен в true, вместо добавления ошибки будет вызвано исключение ActiveModel::StrictValidationFailed. Параметр :strict может быть установлен на любое другое исключение.
person.errors.add(:name, :invalid, strict: true)
# => ActiveModel::StrictValidationFailed: Name is invalid
person.errors.add(:name, :invalid, strict: NameIsInvalid)
# => NameIsInvalid: Name is invalid
person.errors.messages # => {}
attribute должно быть установлено в :base, если ошибка не напрямую связана с одним атрибутом.
person.errors.add(:base, :name_or_email_blank,
message: "either name or email must be present")
person.errors.messages
# => {:base=>["either name or email must be present"]}
person.errors.details
# => {:base=>[{error: :name_or_email_blank}]}
# File activemodel/lib/active_model/errors.rb, line 372
def added?(attribute, type = :invalid, options = {})
attribute, type, options = normalize_arguments(attribute, type, **options)
if type.is_a? Symbol
@errors.any? { |error|
error.strict_match?(attribute, type, **options)
}
else
messages_for(attribute).include?(type)
end
end Возвращает true, если ошибка соответствует предоставленным attribute и type, или false в противном случае. type обрабатывается так же, как для add.
person.errors.add :name, :blank person.errors.added? :name, :blank # => true person.errors.added? :name, "can't be blank" # => true
Если для ошибки требуются параметры, то возвращает true с правильными параметрами или false с неправильными или отсутствующими параметрами.
person.errors.add :name, :too_long, count: 25 person.errors.added? :name, :too_long, count: 25 # => true person.errors.added? :name, "is too long (maximum is 25 characters)" # => true person.errors.added? :name, :too_long, count: 24 # => false person.errors.added? :name, :too_long # => false person.errors.added? :name, "is too long" # => false
# File activemodel/lib/active_model/errors.rb, line 247 def as_json(options = nil) to_hash(options && options[:full_messages]) end
Возвращает Hash, который можно использовать в качестве JSON-представления этого объекта. Вы можете передать параметр :full_messages. Это определяет, должен ли JSON-объект содержать полные сообщения или нет (по умолчанию false).
person.errors.as_json # => {:name=>["cannot be nil"]}
person.errors.as_json(full_messages: true) # => {:name=>["name cannot be nil"]}
# File activemodel/lib/active_model/errors.rb, line 237 def attribute_names @errors.map(&:attribute).uniq.freeze end
Возвращает все имена атрибутов ошибок
person.errors.messages # => {:name=>["cannot be nil", "must be specified"]}
person.errors.attribute_names # => [:name]
# File activemodel/lib/active_model/errors.rb, line 80
Очищает все ошибки. Однако очистка ошибок не делает модель валидной. При следующем запуске валидации (например, через ActiveRecord::Validations#valid?), коллекция ошибок будет снова заполнена, если какие-либо валидации завершатся неудачно.
# File activemodel/lib/active_model/errors.rb, line 215
def delete(attribute, type = nil, **options)
attribute, type, options = normalize_arguments(attribute, type, **options)
matches = where(attribute, type, **options)
matches.each do |error|
@errors.delete(error)
end
matches.map(&:message).presence
end Удаляет сообщения об ошибках для key. Возвращает удаленные сообщения.
person.errors[:name] # => ["cannot be nil"] person.errors.delete(:name) # => ["cannot be nil"] person.errors[:name] # => []
# File activemodel/lib/active_model/errors.rb, line 276
def details
hash = group_by_attribute.transform_values do |errors|
errors.map(&:details)
end
hash.default = EMPTY_ARRAY
hash.freeze
hash
end Возвращает Hash атрибутов с массивом их подробностей об ошибках.
# File activemodel/lib/active_model/errors.rb, line 67
Итерируется по каждому объекту ошибки.
person.errors.add(:name, :too_short, count: 2)
person.errors.each do |error|
# Will yield <#ActiveModel::Error attribute=name, type=too_short,
options={:count=>3}>
end # File activemodel/lib/active_model/errors.rb, line 90
Возвращает true, если ошибок нет.
# File activemodel/lib/active_model/errors.rb, line 451 def full_message(attribute, message) Error.full_message(attribute, message, @base) end
Возвращает полное сообщение для заданного атрибута.
person.errors.full_message(:name, 'is invalid') # => "Name is invalid"
# File activemodel/lib/active_model/errors.rb, line 415 def full_messages @errors.map(&:full_message) end
Возвращает все полные сообщения об ошибках в массиве.
class Person validates_presence_of :name, :address, :email validates_length_of :name, in: 5..30 end person = Person.create(address: '123 First St.') person.errors.full_messages # => ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"]
# File activemodel/lib/active_model/errors.rb, line 430 def full_messages_for(attribute) where(attribute).map(&:full_message).freeze end
Возвращает все полные сообщения об ошибках для данного атрибута в массиве.
class Person validates_presence_of :name, :email validates_length_of :name, in: 5..30 end person = Person.create() person.errors.full_messages_for(:name) # => ["Name is too short (minimum is 5 characters)", "Name can't be blank"]
# File activemodel/lib/active_model/errors.rb, line 479
def generate_message(attribute, type = :invalid, options = {})
Error.generate_message(attribute, type, @base, options)
end Переводит сообщение об ошибке в его стандартном контексте (activemodel.errors.messages).
Error сообщения сначала ищутся в activemodel.errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE, если их нет, ищутся в activemodel.errors.models.MODEL.MESSAGE, а если и там нет, возвращается перевод стандартного сообщения (например, activemodel.errors.messages.MESSAGE). Для интерполяции доступны переведенное имя модели, переведенное имя атрибута и значение.
При использовании наследования в ваших моделях, он также будет проверять все унаследованные модели, но только если модель сама не найдена. Допустим, у вас есть class Admin < User; end и вы хотели перевод для ошибки :blank для атрибута title, он ищет эти переводы:
-
activemodel.errors.models.admin.attributes.title.blank -
activemodel.errors.models.admin.blank -
activemodel.errors.models.user.attributes.title.blank -
activemodel.errors.models.user.blank -
любой стандартный, который вы предоставили через хеш
options(в контекстеactivemodel.errors) -
activemodel.errors.messages.blank -
errors.attributes.title.blank -
errors.messages.blank
# File activemodel/lib/active_model/errors.rb, line 154
def import(error, override_options = {})
[:attribute, :type].each do |key|
if override_options.key?(key)
override_options[key] = override_options[key].to_sym
end
end
@errors.append(NestedError.new(@base, error, override_options))
end Импортирует одну ошибку. Импортированные ошибки оборачиваются в NestedError, предоставляя доступ к исходному объекту ошибки. Если атрибут или тип нужно переопределить, используйте override_options.
Параметры
-
:attribute- Переопределить атрибут, к которому относится ошибка. -
:type- Переопределить тип ошибки.
# File activemodel/lib/active_model/errors.rb, line 202
def include?(attribute)
@errors.any? { |error|
error.match?(attribute.to_sym)
}
end Возвращает true если сообщения об ошибках содержат ошибку для данного ключа attribute, false в противном случае.
person.errors.messages # => {:name=>["cannot be nil"]}
person.errors.include?(:name) # => true
person.errors.include?(:age) # => false
# File activemodel/lib/active_model/errors.rb, line 174
def merge!(other)
return errors if equal?(other)
other.errors.each { |error|
import(error)
}
end Объединяет ошибки из other, каждое Error обернуто как NestedError.
Параметры
-
other- ЭкземплярActiveModel::Errors.
Примеры
person.errors.merge!(other)
# File activemodel/lib/active_model/errors.rb, line 268 def messages hash = to_hash hash.default = EMPTY_ARRAY hash.freeze hash end
Возвращает Hash атрибутов с массивом их сообщений об ошибках.
# File activemodel/lib/active_model/errors.rb, line 444 def messages_for(attribute) where(attribute).map(&:message) end
Возвращает все сообщения об ошибках для заданного атрибута в массиве.
class Person validates_presence_of :name, :email validates_length_of :name, in: 5..30 end person = Person.create() person.errors.messages_for(:name) # => ["is too short (minimum is 5 characters)", "can't be blank"]
# File activemodel/lib/active_model/errors.rb, line 395
def of_kind?(attribute, type = :invalid)
attribute, type = normalize_arguments(attribute, type)
if type.is_a? Symbol
!where(attribute, type).empty?
else
messages_for(attribute).include?(type)
end
end Возвращает true если присутствует ошибка в атрибуте с заданным типом, или false в противном случае. type обрабатывается так же, как для add.
person.errors.add :age person.errors.add :name, :too_long, count: 25 person.errors.of_kind? :age # => true person.errors.of_kind? :name # => false person.errors.of_kind? :name, :too_long # => true person.errors.of_kind? :name, "is too long (maximum is 25 characters)" # => true person.errors.of_kind? :name, :not_too_long # => false person.errors.of_kind? :name, "is too long" # => false
# File activemodel/lib/active_model/errors.rb, line 103 def_delegators :@errors, :each, :clear, :empty?, :size, :uniq!
Возвращает количество ошибок.
# File activemodel/lib/active_model/errors.rb, line 256
def to_hash(full_messages = false)
message_method = full_messages ? :full_message : :message
group_by_attribute.transform_values do |errors|
errors.map(&message_method)
end
end Возвращает Hash атрибутов с их сообщениями об ошибках. Если full_messages равно true, он будет содержать полные сообщения (см. full_message).
person.errors.to_hash # => {:name=>["cannot be nil"]}
person.errors.to_hash(true) # => {:name=>["name cannot be nil"]}
# File activemodel/lib/active_model/errors.rb, line 189
def where(attribute, type = nil, **options)
attribute, type, options = normalize_arguments(attribute, type, **options)
@errors.select { |error|
error.match?(attribute, type, **options)
}
end Поиск ошибок, соответствующих attribute, type, или options.
Сопоставятся только предоставленные параметры.
person.errors.where(:name) # => all name errors. person.errors.where(:name, :too_short) # => all name errors being too short person.errors.where(:name, :too_short, minimum: 2) # => all name errors being too short and minimum is 2
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.