我从早上起就一直在努力解决这个问题,现在是我国的凌晨3点。
我只有一个比尔模型:
class Bill < ActiveRecord::Base
has_many :bill_lines, inverse_of: :bill
validates_associated :bill_lines
accepts_nested_attributes_for :bill_lines, allow_destroy: true
after_validation :calculate_totals
def calculate_totals
self.total = self.bill_lines.sum(:total)
self.tax_total = self.bill_lines.sum(:tax_total)
self.grand_total = self.bill_lines.sum(:grand_total)
end
end
还有:
class BillLine < ActiveRecord::Base
belongs_to :bill, inverse_of: :bill_lines
has_many :bill_line_taxes
has_many :taxes, through: :bill_line_taxes
validates_associated :bill_line_taxes
validates :bill, presence: true
validates :quantity, presence: true, numericality: true
validates :price, presence: true, numericality: true
accepts_nested_attributes_for :bill_line_taxes, allow_destroy: true
after_validation :calculate_totals
def calculate_totals
self.total = self.price * self.quantity
self.grand_total = self.total
self.taxes.each do |tax|
rate = Tax.find(tax.id).tax_rate
self.grand_total = self.grand_total + ( rate / 100 ) * self.grand_total
end
self.tax_total = self.grand_total - self.total
true
end
end
我得到了结果:
bill = FactoryGirl.create(:bill)
bill.total # 50.0 as expected
bill.tax_total # 0.0
bill.grand_total # 50.0
我尝试了self.taxes.each和self.bill_line_taxes.each以及许多回调,如after_save,before_validation等。我无法在回调中达到税ids。但是关联正确地保存到数据库中。如果我验证代码bill.bill_lines.first.valid?比bill.save,税额被添加到数据库(我想这是因为这次关联已经在数据库中了。)
我不确定这是否是我尝试的最佳做法,所以我愿意接受任何改变我的方法的建议。但无论如何要在after_validation回调中获得相关的税ids,我们非常感激。
答案 0 :(得分:1)
您无法在回调中获取ID,因为它们尚未保留在您的数据库中,并且您想要加入,因为没有记录,它将永远无法工作。 after_save 回调会为记录保留一个ID,但除非after_commit您的新数据,否则无法获得该ID。只有持久化的记录才有ID。
你有两个案例
解决方案:
案例1:
前
f.fields_for :bill_line_items do |s|
s.fileds_for :taxes do ....
这将帮助您构建整个记录而不保存它们,因此bill_line_tax将使用它构建一个税务记录,将您的循环更改为
self.bill_line_taxs.each do |bill_line_tax|
rate = bill_line_tax.tax.tax_rate
self.grand_total = self.grand_total + ( rate / 100 ) * self.grand_total
end
案例2: 如果它是一对多,就像我说你的代码将会工作找到。
class BillLine < ActiveRecord::Base
belongs_to :bill, inverse_of: :bill_lines
has_many :taxes
validates_associated :taxes
validates :bill, presence: true
validates :quantity, presence: true, numericality: true
validates :price, presence: true, numericality: true
accepts_nested_attributes_for :taxes, allow_destroy: true
after_validation :calculate_totals
def calculate_totals
self.total = self.price * self.quantity
self.grand_total = self.total
self.taxes.each do |tax|
rate = tax.tax_rate
self.grand_total = self.grand_total + ( rate / 100 ) * self.grand_total
end
self.tax_total = self.grand_total - self.total
true
end
end
在您的表单中
f.fields_for :taxes do |s|
// taxes attributes
f表示您的案例中的BillLine的父对象或您处理表单的任何内容。但请确保它与我所说明的完全嵌套,以便在回调中自动获取构建的对象。