Ruby-on-rails Rails:仅在创建时验证,或当字段不为空时在更新时验证
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24279948/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails: Validate only on create, or on update when field is not blank
提问by Jamie
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 验证仅检查创建或?我正在为我正在开发的应用程序创建一个用户设置页面,问题是,当使用表单提供的参数进行更新时,设置只会在密码和密码确认同时存在时保存。无论怎样,我都希望这些密码字段在创建时进行验证,但仅在提供时进行更新。
回答by cristian
If you want to allow blank values use: allow_blankwith validates.
如果要允许空白值,请使用:allow_blank和验证。
class Topic < ActiveRecord::Base
validates :title, length: { is: 5 }, allow_blank: true
end
If you want to validate only on create, use onwith validates.
如果您只想在创建时验证,请使用on和验证。
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
回答by Jamie
This turned out to be a little simpler than I thought. I changed the form input names from passwordand password_confirmationto new_passwordand 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.
我很肯定有更好的方法来做到这一点(这不是很干)但现在,它有效。仍然非常感谢改进的答案。
回答by Anton Ruban
Is not necessary to change field names, will be enough to replace :password_changed?to :password_digest_changed?in your code.
不需要更改字段名称,在您的代码中替换:password_changed?即可: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?
回答by Sanket
Please try
请尝试
validates :<attributes>, if: Proc.new{|obj| obj.new_record? || !obj.<attribute>.blank? }
or add custom method names instead of attribute name.
或添加自定义方法名称而不是属性名称。
回答by Harry Fairbanks
This works
这有效
validates :password, presence: true, length: { in: 6..20 }, if: :password_digest_changed?
The Bcrypt gem requires that password and password_confirmation are the same so you really only need to worry about one of them. On both, the update and the create the password_digest will change. Meaning that the validation is called on the create and it's only called on the update if the user updates their password. You should have js validation on the front end but this single line of code will protect the db on both the update and create. I have tested this myself. You could probably use custom validations on this but I haven't tried that myself. Late to the game, hope this helps someone.
Bcrypt gem 要求 password 和 password_confirmation 相同,因此您实际上只需要担心其中之一。在两者上,更新和创建 password_digest 都会改变。这意味着验证在创建时被调用,并且只有在用户更新密码时才在更新时调用。您应该在前端进行 js 验证,但这一行代码将在更新和创建时保护数据库。我自己测试过这个。您可能可以对此使用自定义验证,但我自己还没有尝试过。游戏迟到了,希望这对某人有所帮助。

