2

I have an Order, an Item and a Product model.

class Order < ApplicationRecord
  has_many :items, dependent: :destroy, inverse_of: :order
end

class Item < ApplicationRecord
  belongs_to :order
  belongs_to :product
end

class Product < ApplicationRecord
  has_many :items
end

I need to calculate how many boxes every Item has (item.units/item.product.units_per_box), in a before_save callback, but I can't access the nested attributes, just the persisted items.

I've this in the Order model:

before_save :calculate_boxes, on: [:create, :update]

def calculate_boxes
  self.boxes = 0
  self.items.each do |item|
    self.boxes += item.units / item.product.units_per_box
  end
end

But, how I said, it just calculates the persisted items.

Don't know if it matters, but I am using @nathanvda's Cocoon gem to manage nested attributes on the create/edit form.

pzin
  • 4,200
  • 2
  • 28
  • 49
  • What are you trying to accomplish? It looks like not following convention. You can also use `after_save` if it only gives you the persisted items – Nermin Sep 25 '18 at 07:13
  • If I user an `after_save` callback to do the calculations and then save the Order, it will fire an infinite loop. I want to set the total amount of boxes ordered in the order, units are stored in Item model and the unit per box in de product model. – pzin Sep 25 '18 at 08:03
  • Try using self.items.collect. That should work. Also i would suggest you to use unless item.marked_for_destruction? inside the loop. – Akshay Goyal Sep 25 '18 at 10:04
  • Also using on: [:create, :update] doesn't make much sense. before_save callback silently ignores "on" arguments. I would suggest you to use before_create and before_update callbacks instead. – Akshay Goyal Sep 25 '18 at 10:14
  • @Akshay `.collect` worked nice. Please, post your comment as an answer to accept it. – pzin Sep 25 '18 at 15:22

1 Answers1

3

Try using self.items.collect. That should work. Also i would suggest you to use unless item.marked_for_destruction? inside the loop.

Akshay Goyal
  • 895
  • 5
  • 13