首页 > 解决方案 > 验证失败,因为验证存在不尊重 rails 5

问题描述

我的Transaction模型属于 2 UserWallet( sender_wallet, receiver_wallet) 个实例。我验证了这两个实例的存在,以及其他属性currency, amount... 在创建时,我还确保sender_wallet有足够的资金来创建该交易

class Transaction < ApplicationRecord
  belongs_to :sender_wallet, class_name: 'UserWallet'
  belongs_to :receiver_wallet, class_name: 'UserWallet'

  validates :sender_wallet, :receiver_wallet, :amount, :currency, presence: true

  validate :validate_balance, on: :create

  def validate_balance
    if sender_wallet.balance < amount
      errors.add(:amount, 'Not enough money')
    end
  end
end

问题是当belong_to对 sender_wallet 使用 shoulda-matcher 时,它将 sender_wallet 设置为 nil,并调用抛出的 validate_balance

NoMethodError: undefined method `balance' for nil:NilClass

不应该因为 sender_wallet 没有设置而失败吗?我尝试使用控制台深入研究它,当我这样做时

Transaction.create(amount: 10000, currency: 'EUR')

它以同样的方式失败

谢谢你的帮助

标签: ruby-on-rails

解决方案


所有的验证都将被一一撤销。因此,根据您的代码,首先,它将验证存在,然后 validate_balance。

现在,在 validate_balance 验证中,您的 sender_wallet nil 会导致此错误。

通过以下三种方式在 validate_balance 方法之前更好地检查 sender_wallet 是否存在:

  1. 在您的验证码中

    validate :validate_balance, on: :create, if: -> { sender_wallet_id.present? }
    
  2. 在您的 validate_balance 方法中

    def validate_balance
      if sender_wallet.present? && sender_wallet.balance < amount
         errors.add(:amount, 'Not enough money')
      end
    end
    
  3. 使用 try(:attribute),这不会产生异常。

    def validate_balance   
      if sender_wallet.try(:balance) < amount
        errors.add(:amount, 'Not enough money') 
      end 
    end
    

推荐阅读