Chinedu Lloyd Abalogu Chinedu Lloyd Abalogu - 7 months ago 8
SQL Question

after_update callback won't update attribute

Good day... I have implemented an after_update callback for a specific column that will be updated, and after that column is updated the callback is meant to add the newly updated value to another column i.e

class Product < ActiveRecord::Base
after_update :update_stock, :if => :produced_changed?

private

def update_stock
self.stock = self.stock + self.produced
end
end


When i run rails console and run "Product.update produced:450" the stock column will automatically add the new value. i.e it works perfectly but when I try updating from the "view/controller" it doesn't work at all.

please is there a reason why?

2.2.4 :004 > h
=> Product id: 1, name: "MAC Air Filter", partnumber: 33440, description: "Air filter", stock: 3440, created_at: "2016-04-08 11:38:58", updated_at: "2016-04-19 20:33:00", produced: 33

2.2.4 :006 > h.update produced:3000
(0.1ms) SAVEPOINT active_record_1
SQL (1.4ms) UPDATE "products" SET "produced" = ?, "updated_at" = ? WHERE "products"."id" = ? [["produced", 3000], ["updated_at", "2016-04-20 13:57:59.377954"], ["id", 1]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> true

2.2.4 :007 > h
=> Product id: 1, name: "MAC Air Filter", partnumber: 33440, description: "Air filter", stock: 6440, created_at: "2016-04-08 11:38:58", updated_at: "2016-04-20 13:57:59", produced: 3000>

Answer

You have save the product stock to update the product. Here in the update_stock callback you only set the value of product stock. self.stock = self.stock + self.produced only set the value of product stock.

To update the stock value you have to save in callback as:

class Product < ActiveRecord::Base
after_update :update_stock, :if => :produced_changed?

private 

def update_stock
    self.stock = self.stock + self.produced
    self.save
end     
end

But it runs the infinite loop and gives error. So you have to set the stock value before update using before_update callback.

  class Product < ActiveRecord::Base
    before_update :update_stock, :if => :produced_changed?

    private 

    def update_stock
        self.stock = self.stock + self.produced
    end     
 end

And save the value of product in controller.