class Car < ActiveRecord::Base
has_many :adverts
end
class Advert < ActiveRecord::Base
belongs_to :car
end
I also have an observer on Advert
that looks like this:
class AdvertObserver < ActiveRecord::Observer
def before_save advert
@should_update_car_price = advert.price_changed?
return true #An ActiveRecord::RecordNotSaved will be thrown if return false
end
def after_commit advert
enqueue_car_price_refresh_job_if_necessary(advert)
reset_async_processing_indicators!
end
def reset_async_processing_indicators!
@should_update_car_price = nil
end
#
# Async processing
#
def enqueue_car_price_refresh_job_if_necessary advert
WorkerJobs::CarPriceRefreshJob.perform_async(advert.car_id) if @should_update_car_price
end
end
Now, the basic idea is, that I need to make sure that the async_processing of the CarPriceRefreshJob
is first enqueued for processing AFTER the advert has been persisted. The problem is though, that it depends if the advert.price
has changed or not (dirty) which is not available in an after_commit
. This is why I instead set a "flag" in before_save
: @should_update_car_price
. This seems to work, however there seems to be a few cases in my database where the price on car was NOT synced with the advert (the async job was not run, maybe not enqueued). If I manually enqueue the CarPriceRefreshJob
for one of these not updated records, it updates as it should, and hence I'm suspecting the callback rather than the job itself.
As stated I'm suspecting the implementation I made of the callback, but I'm very unsure how I can possible debug it? I made tests for all cases I can think of, and they all pass.
I'm running rails 4 BTW with postgresql 9.3
Don't use instance variables on Observers. They are singletons and therefore the instance variables persist when observing other objects.
http://www.rubydoc.info/gems/rails-observers/0.1.2/ActiveRecord/Observer
This should be catched with a test that saves 2 objects one after another in the same spec.