Skip to content

Instantly share code, notes, and snippets.

@searls
Created January 11, 2022 15:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save searls/12f88787487d044c0ffe9223ef0984e4 to your computer and use it in GitHub Desktop.
Save searls/12f88787487d044c0ffe9223ef0984e4 to your computer and use it in GitHub Desktop.
I mistakenly thought that re-assigning all entries on an association would cascade a save! on the owner of the relationship to the depended models if they were dirty. Turns out, nope!
class CountsInventory
def count_inventory(store)
Inventory.find_or_initialize_by(store: store).tap do |inventory|
inventory.assign_attributes(date: Time.zone.now.to_date)
inventory.items = count_items(inventory) # Updates which items are associated, does not cascade save to them
inventory.save!
end
end
def count_items(inventory)
Item.where("stock > 0").find_each do |item|
InventoryItem.find_or_initialize_by(inventory: inventory, item: item).tap do |inventory_item|
inventory_item.assign_attributes(count: item.stock) # Will not change on subsequent runs!
end
end
end
end
store = Store.first
Item.create!(store: store, stock: 2)
CountsInventory.new.call(store)
inventory.items.first.count # 2!
Item.find_by(store: store).update!(stock: 4)
inventory = CountsInventory.new.call(store)
inventory.items.first.count # 4, good!
inventory.items.first.reload.count # 2! Oh no!
@searls
Copy link
Author

searls commented Jan 11, 2022

FYI, this was fixed by setting autosave: true on the has_many association!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment