【发布时间】:2014-06-18 07:54:32
【问题描述】:
当字段不为空时,如何限制 Rails 验证只检查创建或?我正在为我正在开发的应用程序创建一个用户设置页面,问题是,当使用表单提供的参数进行更新时,设置只会在密码和密码确认都存在时保存。无论如何,我希望这些密码字段在创建时验证,但仅在提供时更新。
【问题讨论】:
标签: ruby-on-rails ruby rails-activerecord
当字段不为空时,如何限制 Rails 验证只检查创建或?我正在为我正在开发的应用程序创建一个用户设置页面,问题是,当使用表单提供的参数进行更新时,设置只会在密码和密码确认都存在时保存。无论如何,我希望这些密码字段在创建时验证,但仅在提供时更新。
【问题讨论】:
标签: ruby-on-rails ruby rails-activerecord
如果您想允许空白值,请使用:allow_blank with validates。
class Topic < ActiveRecord::Base
validates :title, length: { is: 5 }, allow_blank: true
end
如果您只想在创建时进行验证,请将on 与验证一起使用。
class Topic < ActiveRecord::Base
validates :email, uniqueness: true, on: :create
end
覆盖你的情况:
class Topic
validates :email, presence: true, if: :should_validate?
def should_validate?
new_record? || email.present?
end
end
【讨论】:
if: :should_validate? 非常有用,而且高度可定制。谢谢。
事实证明这比我想象的要简单一些。我将表单输入名称从password 和password_confirmation 更改为new_password 和new_password_confirmation。我使用以下行在我的模型中为这些值添加了临时访问器:
attr_accessor :new_password, :new_password_confirmation
我实现了一个password_changed? 方法,定义如下:
def password_changed?
!new_password.blank?
end
最后,我将验证更改为:
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?
我很肯定有更好的方法来做到这一点(这不是很干),但现在,它有效。改进的答案仍然非常感谢。
【讨论】:
无需更改字段名称,将代码中的: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?
【讨论】:
请尝试
validates :<attributes>, if: Proc.new{|obj| obj.new_record? || !obj.<attribute>.blank? }
或添加自定义方法名称而不是属性名称。
【讨论】:
->(obj) { obj.new_record? || ... }
validates :password, confirmation: true, presence: true, length: { in: 6..20 }, if: ->(obj) { obj.new_record? || !obj.password.blank? }
这行得通
validates :password, presence: true, length: { in: 6..20 }, if: :password_digest_changed?
Bcrypt gem 要求 password 和 password_confirmation 相同,所以你真的只需要担心其中一个。在两者上,密码摘要的更新和创建都会改变。这意味着验证是在创建时调用的,并且只有在用户更新密码时才会在更新时调用。您应该在前端进行 js 验证,但是这一行代码将在更新和创建时保护数据库。我自己对此进行了测试。您可能可以对此使用自定义验证,但我自己没有尝试过。游戏迟到了,希望这对某人有所帮助。
【讨论】: