How can I restrict a Rails validation to check only on create OR when the field isn't blank? I'm creating a user settings page for an app I'm working on and the problem is that, when updating using the parameters provided by the form, the settings will only save when both a password and password confirmation are present. I would like these password fields to validate on create no matter what, but only on update when they are provided.
If you want to allow blank values use: allow_blank with validates.
class Topic < ActiveRecord::Base
validates :title, length: { is: 5 }, allow_blank: true
end
If you want to validate only on create, use on with validates.
class Topic < ActiveRecord::Base
validates :email, uniqueness: true, on: :create
end
To cover your case:
class Topic
validates :email, presence: true, if: :should_validate?
def should_validate?
new_record? || email.present?
end
end
This turned out to be a little simpler than I thought. I changed the form input names from password
and password_confirmation
to new_password
and new_password_confirmation
. I added temporary accessors for these values in my model using the following line:
attr_accessor :new_password, :new_password_confirmation
I implemented a password_changed?
method defined as follows:
def password_changed?
!new_password.blank?
end
Finally, I changed my validations to:
validates :new_password, presence: true, confirmation: true, length: { in: 6..20 }, on: :create
validates :new_password, presence: true, confirmation: true, length: { in: 6..20 }, on: :update, if: :password_changed?
validates :new_password_confirmation, presence: true, on: :create
validates :new_password_confirmation, presence: true, on: :update, if: :password_changed?
I'm positive there's a better way to do this (this isn't very DRY) but for now, it works. Improved answers would still be very much appreciated.
It is not necessary to change field names, will be enough to replace :password_changed?
to :password_digest_changed?
in your code.
validates :password, presence: true, confirmation: true, length: { in: 6..20 }, on: :create
validates :password, presence: true, confirmation: true, length: { in: 6..20 }, on: :update, if: :password_digest_changed?
validates :password_confirmation, presence: true, on: :create
validates :password_confirmation, presence: true, on: :update, if: :password_digest_changed?
Please try
validates :<attributes>, if: Proc.new{|obj| obj.new_record? || !obj.<attribute>.blank? }
or add custom method names instead of attribute name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With