在验证中使用嵌套属性中的参数

时间:2012-12-22 23:06:09

标签: ruby-on-rails ruby-on-rails-3 activerecord

我正在构建一个简单的会计应用程序。事务有许多条目,每个条目属于一个事务。每个条目都是借方或贷方分录。所有借方的“金额”字段的总和必须等于每笔交易的所有贷方的总和。所以在我的交易模型中,我有以下内容:

Transaction.rb

attr_accessible :entries_attributes
has_many :entries
accepts_nested_attributes_for :entries

validate :entries_sum_to_zero

private

    def entries_sum_to_zero
        errors.add(:base, "Debits and credits must balance.") unless self.entries.where(:entry_type => 'Credit').sum(:amount) == self.entries.where(:entry_type => 'Debit').sum(:amount)
    end 

但这不起作用。它不会抛出错误,但如果不满足条件,它也不会停止事务并且所有条目都将保存到数据库中。我认为这可能与条目模型中的'amount'在entries_attributes的params哈希中有关。是这样的吗?如果是这样,在保存交易之前,如何重写上述代码以将entries_attributes params哈希中的金额相加?

感谢。

更新:

我也试过了,但它似乎也没有用:

before_save :entries_sum_to_zero

private
    def entries_sum_to_zero
       if self.entries.where(:entry_type => 'Credit').sum(:amount) != self.entries.where(:entry_type => 'Debit').sum(:amount)
           errors.add(:base, "Debits and credits must balance.")
           return false
       end
    end

更新2:

我最终通过将验证移到控制器中来实现它。但是,如何将其移回模型中,以便将验证保存在一个位置?

def create
    @company = Company.find(params[:company_id])
    @transaction = @company.transactions.new(params[:transaction])
    sum_of_debits = 0
    sum_of_credits = 0      
    params[:transaction]['entries_attributes'].each do |k,v|
        sum_of_debits += v['amount'].to_i if v['entry_type'] == "Debit"
        sum_of_credits += v['amount'].to_i if v['entry_type'] == "Credit"
    end
    if sum_of_credits != sum_of_debits
        flash[:error] = "Debits and Credits must balance."
        render 'new'
    else        
        if @transaction.save
            flash[:success] = "Transaction added"
            redirect_to company_path(@company)
        else
            render 'new'
        end   
    end       
end

1 个答案:

答案 0 :(得分:0)

验证方法中的问题。您向数据库询问两个总和并且验证顺利,因为您的新条目尚未存在于数据库中。你必须只检查entries_attributes(因为我们可以假设,然后在数据库中一切正常)