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.
当字段不为空时,如何限制Rails验证以仅检查创建OR?我正在为我正在处理的应用程序创建用户设置页面,问题是,当使用表单提供的参数进行更新时,只有在存在密码和密码确认时才会保存设置。我想这些密码字段在创建时无论如何都要验证,但只有在提供时才更新。
4 个解决方案
#1
33
If you want to allow blank values use: allow_blank with validates.
如果要允许空值,请使用: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.
如果只想在create上验证,请使用on 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
#2
9
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:
事实证明这比我想象的要简单一些。我将表单输入名称从password和password_confirmation更改为new_password和new_password_confirmation。我使用以下行在我的模型中为这些值添加了临时访问器:
attr_accessor :new_password, :new_password_confirmation
I implemented a password_changed?
method defined as follows:
我实现了password_changed?方法定义如下:
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.
我很肯定有更好的方法来做到这一点(这不是很干)但是现在,它有效。仍然非常感谢改进的答案。
#3
5
Please try
请尝试
validates :<attributes>, if: Proc.new{|obj| obj.new_record? || !obj.<attribute>.blank? }
or add custom method names instead of attribute name.
或添加自定义方法名称而不是属性名称。
#4
3
Is not necessary to change field names, will be enough to replace :password_changed?
to :password_digest_changed?
in your code.
没有必要更改字段名称,将足以替换:password_changed? to:password_digest_changed?在你的代码中。
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?
#1
33
If you want to allow blank values use: allow_blank with validates.
如果要允许空值,请使用: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.
如果只想在create上验证,请使用on 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
#2
9
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:
事实证明这比我想象的要简单一些。我将表单输入名称从password和password_confirmation更改为new_password和new_password_confirmation。我使用以下行在我的模型中为这些值添加了临时访问器:
attr_accessor :new_password, :new_password_confirmation
I implemented a password_changed?
method defined as follows:
我实现了password_changed?方法定义如下:
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.
我很肯定有更好的方法来做到这一点(这不是很干)但是现在,它有效。仍然非常感谢改进的答案。
#3
5
Please try
请尝试
validates :<attributes>, if: Proc.new{|obj| obj.new_record? || !obj.<attribute>.blank? }
or add custom method names instead of attribute name.
或添加自定义方法名称而不是属性名称。
#4
3
Is not necessary to change field names, will be enough to replace :password_changed?
to :password_digest_changed?
in your code.
没有必要更改字段名称,将足以替换:password_changed? to:password_digest_changed?在你的代码中。
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?