Rails:仅在创建时进行验证,或在字段不为空时进行更新

时间:2022-09-11 17:35:57

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?