Harakiri
Harakiri

Reputation: 730

Rails: Update parent record, when Child get's saved

I have the following Structure: An Order has_many sales (and a Sale belongs_to an Order).

The totalprice is composed by price x quantity x 12 out of the sales records that belonging to the parent Order.

This is how my calculation looks inside the Order model:

class Order < ActiveRecord::Base
  has_many :sales, dependent: :destroy
  after_save :calc

  def price
   sales.to_a.sum { |item| item.price }
  end

  def totalpricex12
   totalpricex12 = price*12
  end

  def totaldiscount
   sales.to_a.sum { |item| item.discount }
  end

  def calc
   calc = (totalpricex12.to_f)-(totaldiscount.to_f)
   self.update_columns(totalprice: calc)
  end
end

The problem is: totalprice only gets updated, when the Order gets updated or saved, but not if a new Sale gets added or deleted.

Upvotes: 1

Views: 1947

Answers (2)

Richard Peck
Richard Peck

Reputation: 76784

You'll want to use inverse_of:

#app/models/sale.rb
class Sale < ActiveRecord::Base
   belongs_to :order, inverse_of: :sales
   validates  :order, presence: true

   after_create  :update_order
   after_destroy :update_order

   private

   def update_order
      order.calc
   end
end

#app/models/order.rb
class Order < ActiveRecord::Base
   has_many :sales, inverse_of: :order
end

This will give you the respective objects associated to sale / order, which will be made available through the inverse_of method:

When we call criminal.prison without :inverse_of on both the :belongs_to and :has_many associations, it will hit the database. With :inverse_of, if we already have that prison record in memory then criminal.prison will point to the same prison.

Upvotes: 6

axvm
axvm

Reputation: 2113

You can use after_save callback, for example like this:

class Sale < ... 
  belongs_to :order

  after_save do
    order.calc
  end
end

of like this:

class Sale < ... 
  belongs_to :order
  after_save :update_order

  def update_order
    # call parent to self-update or something like this
  end
end

Upvotes: 1

Related Questions