Errors.delete(key) removes all errors for an attribute and I only want to remove a specific type of error belonging to an attribute. This following method can be added to any model.
Returns message if removed, nil otherwise. Internal data structures are modified so all other methods should work as expected after error removal.
Released under the MIT License
Method to remove error from model after validations have been run.
def remove_error!(attribute, message = :invalid, options = {})
# -- Same code as private method ActiveModel::Errors.normalize_message(attribute, message, options).
callbacks_options = [:if, :unless, :on, :allow_nil, :allow_blank, :strict]
case message
when Symbol
message = self.errors.generate_message(attribute, message, options.except(*callbacks_options))
when Proc
message = message.call
else
message = message
end
# -- end block
# -- Delete message - based on ActiveModel::Errors.added?(attribute, message = :invalid, options = {}).
message = self.errors[attribute].delete(message) rescue nil
# -- Delete attribute from errors if message array is empty.
self.errors.messages.delete(attribute) if !self.errors.messages[attribute].present?
return message
end
Usage:
user.remove_error!(:email, :taken)
Method to check validity except specified attributes and messages.
def valid_except?(except={})
self.valid?
# -- Use this to call valid? for superclass if self.valid? is overridden.
# self.class.superclass.instance_method(:valid?).bind(self).call
except.each do |attribute, message|
if message.present?
remove_error!(attribute, message)
else
self.errors.delete(attribute)
end
end
!self.errors.present?
end
Usage:
user.valid_except?({email: :blank})
user.valid_except?({email: "can't be blank"})