2012-07-19 47 views
1

我有2種型號:驗證該部分的總和等於與父母總/兒童記錄

Invoice has_many :lines 

Line belongs_to :invoice 

我想確保Line對於給定Invoice比賽總的總和相關的Invoice

我已經試過這樣:

validate :total_amount 
def total_amount 
    inv_id = self.invoice_id 
    target_amount = Invoice.find(inv_id).total 
    total_lines = Line.where(invoice_id: inv_id).sum(:line_value) 

    errors.add(:total, " should be lower or equal to the total amount of the invoice") if total_lines > target_amount 
end 

  1. 它並不適用於新的對象(只更新)工作
  2. 甚至更​​新系統地拋出一個錯誤

我也看到一個關於AssociatedValidator的問題,但我還沒有能夠掌握如何使用:(

回答

1

我可能解釋是錯誤的,但如果totalinvoices表中的列,我建議刪除它。相反,請將其作爲一種方法,並使方法將價格加上任何調整。否則,您在數據庫中有重複。這樣你就不需要再驗證任何東西:)

在更一般的說明中,在關聯模型ActiveRecord上添加驗證工作不太好。在某些情況下,這幾乎是不可能的,而在其他情況下 - 很難做到正確。我認爲你已經看到它很容易出錯。我建議避免它,並試圖設計你的數據庫,這樣你就不需要(在這種情況下有Invoice#total作爲一種方法)。

2

目前尚不清楚您要驗證的是什麼,因爲您的示例與之前描述的不同。

我覺得這樣的事情應該工作,使用before_add callback

class Invoice < AR::Base 
    has_many :lines, :before_add => :validate_total 

    def validate_total(invoice, line) 
    totals = invoice.lines.sum(:line_value) 

    if totals + line.line_value > invoice.total 
     invoice.errors.add(:total, " should be lower or equal to the total amount of the invoice") 
     return false # I think you can alternatively raise an exception here 
    end 
    ...