I have and Administrator model with devise :
class Administrator < ApplicationRecord
validate :max_num_admins, on: :create
devise :invitable, :database_authenticatable,
:recoverable, :rememberable, :validatable
def max_num_admins
self.errors.add(:base,
I18n.t(
'activerecord.errors.models.administrator.max_reached'
)
) if Administrator.count > 3
end
end
Admins can be added through an admin dashboard by the "account owner", this has the effect of inviting the admin (devise invitable method invite!) :
def create
resource = resource_class.new(resource_params)
authorize_resource(resource)
if resource.valid?
Administrator.invite!(resource_params)
redirect_to(
[namespace, resource],
notice: translate_with_resource('create.success')
)
else
render :new, locals: {
page: Administrate::Page::Form.new(dashboard, resource)
}
end
end
As you can see, I want to check if my record is valid, especially if there are no more than 3 admin records for that account. The problem is when I call valid? on resource(the administrator) I always get false as at this stage the only necessary param to invite an admin is a valid email but devise validations are triggered, and thus I get an error for not setting a password.
What would be a clean way to keep the email and max_num_admins validation triggering for this action but not the password one from devise ?
the validations chain is a chain of callbacks and the result of validations chain is the
errorsafter all (returntrueiferrors.empty?), there's no way to filter (orfail early), so when your model setup devise, all devise's validations is add to the validations chain, no way to filter them out but remove devise. So i came up with the idea that you should define aspecial validationscope that will append at the end of validations chain and will forceerrors.clear(so that it'll ignore previous devise validations), take a look at below code:then
Update
no need to touch any existed validation, you can add at the end of validations chain a validation
specialthat willslice!those errors you want to check:then
note DEPRECATION WARNING: ActiveModel::Errors#slice! is deprecated and will be removed in Rails 6.2.