2

我是 Rails 新手,正在开发我的第一个 Rails 项目,它是一个发票应用程序,在发票表单中包含嵌套行项目。我想在保存发票之前计算总发票。如果只是在保存过程中添加了项目,我可以很好地保存它,但是如果其中一个嵌套的行项目被标记为要删除,它就不能正确计算总数。我将不得不返回并再次保存以获得正确的总账单金额。

class Invoice < ActiveRecord::Base
  attr_accessible :job_name, :items_attributes, :tax1, :tax2, :subtotal

  before_save :calculate_totals


  has_many :items, :dependent => :destroy
  accepts_nested_attributes_for :items, allow_destroy: true

  private

  def calculate_totals
    self.subtotal = 0

    self.items.each do |i|
      self.subtotal = self.subtotal + (i.quantity * i.cost_per)
    end
  end
end

我注意到这与 params 有何不同,但问题项目记录列在请求的参数中,其中 :_destroy = true

{"utf8"=>"✓",
 "_method"=>"put",
 "authenticity_token"=>"+OqRa7vRa1CKPMCdBrjhvU6jzMH1zQ=",
 "invoice"=>{"client_id"=>"1",
 "job_name"=>"dsdsadsad",
 "items_attributes"=>{"0"=>{"name"=>"jhksadhshdkjhkjdh",
 "quantity"=>"1",
 "cost_per"=>"50.0",
 "id"=>"21",
 "_destroy"=>"false"},
 "1"=>{"name"=>"delete this one",
 "quantity"=>"1",
 "cost_per"=>"10.0",
 "id"=>"24",
 "_destroy"=>"true"}}},
 "commit"=>"Update Invoice",
 "id"=>"8"}

谢谢你的帮助。

4

3 回答 3

2

我找到了一个似乎可行的解决方案:

class Invoice < ActiveRecord::Base
  attr_accessible :job_name, :items_attributes, :tax1, :tax2, :subtotal

  before_save :calculate_totals


  has_many :items, :dependent => :destroy
  accepts_nested_attributes_for :items, allow_destroy: true

  private
    def calculate_totals
      self.subtotal = 0

      self.items.each do |i|
        unless i.marked_for_destruction?
          self.subtotal += (i.quantity * i.cost_per)
        end
      end

end

关键是marked_for_destruction的方法吗?在这种情况下,我正在检查未标记为销毁的项目。这是解释它的rails api的链接:http: //api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

谢谢史蒂夫

于 2012-11-15T14:04:33.947 回答
0
params[:invoice][:items_attributes].each do |i|
  self.subtotal = self.subtotal + (i[:quantity].to_f * i[:cost_per].to_f) unless i['_destroy'] == 'true'
end
于 2012-11-15T02:49:59.903 回答
0

您在was saved之前Invoice已经计算过项目,所以它也计算了销毁的项目,如 API 文档中的指南:

请注意,在保存父级之前,模型不会被销毁。

因此,您只需要更改before_saveafter_save,它就会起作用。

于 2012-11-15T06:14:57.270 回答