Ruby on rails 如何在RubyonRails中使用验证更新模型的特定字段?

Ruby on rails 如何在RubyonRails中使用验证更新模型的特定字段?,ruby-on-rails,ruby,Ruby On Rails,Ruby,有一个名为User的AcViterRecord模型,如下所示: class User < ActiveRecord::Base validates :name, :presence => true validates :email, :presence => true, :uniqueness => true validates :plain_password, :presence => true, :confirmation => true

有一个名为
User
的AcViterRecord模型,如下所示:

class User < ActiveRecord::Base
  validates :name, :presence => true
  validates :email, :presence => true, :uniqueness => true

  validates :plain_password, :presence => true, :confirmation => true
  validates :plain_password_confirmation, :presence => true
  #...other codes
end
class用户true
验证:email,:presence=>true,:university=>true
验证:普通密码,:presence=>true,:confirmation=>true
验证:普通密码确认,:状态=>true
#…其他代码
结束
它要求名称和电子邮件的更新与密码的更新分开

仅更新名称和密码时,使用
update
update\u属性将导致不需要的密码验证。但是使用
update\u属性
将保存姓名和电子邮件而无需验证


是否有任何方法可以通过验证更新模型的特定字段,而不会导致其他字段的验证?

您可以调整验证,使其仅在创建时运行。需要确认可确保应用编辑时的更改

validates :plain_password,
          confirmation: true,
          presence: {
            on: :create },
          length: {
            minimum: 8,
            allow_blank: true }

validates :plain_password_confirmation,
          presence: {
            on: :create }
我假设您正在对密码进行哈希运算,因此这将伴随类似于以下代码的代码:

attr_accessor :plain_password

before_save :prepare_password

def encrypted_password( bcrypt_computational_cost = Rails.env.test? ? 1 : 10)
  BCrypt::Password.create plain_password, cost: bcrypt_computational_cost
end

private #===========================================================================================================


# Sets this users password hash to the encrypted password, if the password is not blank.
def prepare_password
  self.password_hash = encrypted_password if plain_password.present?
end

更好的处理方法是不在编辑表单的其余部分包含字段,而是提供“更改我的密码”的链接。此链接将指向一个新表单(可能在模式窗口中),该表单将需要新密码、新密码确认和旧密码,以防止出现错误。

在您的情况下,密码仅在创建时有效

试试看,可能会有帮助

class User < ActiveRecord::Base
  validates :name, presence: true
  validates :email, presence: true, :uniqueness => true

  validates :plain_password, length: { in: 4..255, allow_nil: true }, confirmation: true
  validates :plain_password_confirmation, presence: true, if: -> (user){ user.plain_password.present? }

  # ......
  # ......
end
class用户true
验证:普通密码,长度:{in:4..255,允许\ nil:true},确认:true
验证:普通密码确认,状态:true,如果:->(用户){user.plain密码.present?}
# ......
# ......
结束

除此之外,您还应该重新考虑保存普通\u密码;)

这样做的副作用是将散列密码限制在72个字符以内。我不太理解你的问题。你认为72个字符还不够吗?我认为人为地对散列密码施加一个下限不必要地影响了应用程序的安全性,没有任何好处。是否足够。。。也许对于某些网站来说这已经足够了,但我的电子邮件和银行密码肯定比这长…@Jerry,但这通常是通过密码哈希逻辑来处理的。我更新了答案以反映这一点。希望您没有将明文密码存储在数据库中……明文密码和明文密码确认都是虚拟属性,不会存储在数据库中。我的代码中也有散列逻辑,但我不知道是否可以在散列逻辑中处理状态检查。如果不能这样处理,这是否意味着普通密码的存在:{on::create}
可以从
validates
指令中删除?@Brad_-Werth,当
普通密码
没有出现时,是否应该在散列逻辑中的
错误[:普通密码]
后附加一条错误消息?@Jerry Good,这假设了虚拟属性——最好的方法。如果您只是不保存散列,那么在您现有的方法中,当密码为空时,您应该可以继续。创建时检查是否存在可确保不能使用空密码创建新用户,因此我建议将该位保留在其中。如果在创建过程中密码或确认为空,或者在编辑过程中密码或确认字段已填充且不匹配,则会出现错误。假设在编辑过程中,如果他们没有输入任何内容,则内容将保持不变。