Rails:如何区分保持属性不变与显式将新值设置为与旧值相同?

Rails: how to tell the difference between leaving an attribute unchanged vs explicitly setting the new value to be the same as the old value?

ActiveRecord Useremailemail_verified。如果电子邮件发生变化,它将 email_verified 设置为 false 使用:

before_save :process_new_email, if: :email_changed?

process_new_email 基本上就是:

def process_new_email
   self.email_verified = false
end

但是,对于 user.update(email: email, email_verified: true),如果 email_verified 之前是 true,这也会将 email_verified 设置为 false。

即这失败了:

      user = create(:user, email: 'test@example.com', email_verified: true)
      user.update!(email: 'other@example.com', email_verified: true)
      expect(user.email_verified).to eq(true)

这就过去了:

      user = create(:user, email: 'test@example.com', email_verified: true)
      user.update!(email: 'other@example.com')
      expect(user.email_verified).to eq(false)

如何让两个测试用例都通过?

我认为您可以使用 ActiveRecord 为您创建的 email_verified_came_from_user? 方法(它为每个属性创建该方法)。

例如检查这个:

user = User.find_by(email: 'test@example.com')
user.email_came_from_user? # => false
user.email = 'test@example.com' # setting the same so no change
user.email_came_from_user? # => true

所以,我会做类似的事情:

def process_new_email
  self.email_verified = false unless email_verified_came_from_user?
end

如果已更改,请尝试还原 email_verified。

before_save :revert_email_verified, if: :email_verified_changed?
before_save :process_new_email, if: :email_changed?

def revert_email_verified
  self.email_verified = email_verified_was
end