I have an “order” model which has_many lineitems. I need to populate a column on order, lets call it search_body that has certain information about the order and each line item in the order, for easy search.
So, when lineitems are added or removed I need this search_body field updated.
Right now I have an after_save and after_destroy callback in the lineitem that references the order:
after_save ->(lineitem) { lineitem.order.save }
It just feels wrong. Is there any way that the parent model (order) can be aware of changes in associated models and update this column when items are removed or added to an association?
class LineItem < ActiveRecord::Base
belongs_to :order, touch: :true
end
This way, every time a lifetime is changed the Order is updated. In your order you could then use an after_touch callback there. However, you could try moving all of this logic out of your models and into a service object that does it.
class UpdateLineItem
def initialize(lineitem)
@lineitem = lineitem
end
def run
@lineitem.save
# do whatever with @lineitem.order
end
end
What would be the best way to instantiate that service object from the lineitem being saved? Replace the save method or use a callback? This is a new problem for me.
I wouldn’t instantiate in your model. If you think about it LineItem has no reason to know about this service, let alone directly called from within one of its methods. I would start by looking at the controller level for a place to call the service.