class Car < ActiveRecord::Base
has_many :adverts
end
class Advert < ActiveRecord::Base
belongs_to :car
end
我还有Advert
的观察者看起来像这样:
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
现在,基本的想法是,我需要确保CarPriceRefreshJob
的async_processing首先排队,以便在广告被保留后进行处理。但问题是,它取决于advert.price
是否已经改变(脏),这在after_commit
中是不可用的。这就是我在before_save
:@should_update_car_price
中设置“标志”的原因。这似乎有效,但是在我的数据库中似乎有一些案例,其中汽车价格未与广告同步(异步作业未运行,可能没有排队)。如果我手动将CarPriceRefreshJob
列入其中一个未更新的记录,它会更新,因此我怀疑是回调而不是作业本身。
如上所述,我怀疑我对回调的实现,但我不确定如何调试它?我对我能想到的所有案例进行了测试,并且都通过了。
我正在使用postgresql 9.3运行rails 4 BTW
答案 0 :(得分:1)
请勿在Observers上使用实例变量。它们是单例,因此在观察其他对象时实例变量仍然存在。
加载观察者在他们观察到的模型类中注册自己, 因为它是在发生事件时通知他们的类。如 副作用,当观察者加载其相应的模型时 加载了类。
最多(包括)Rails 2.0.2观察者之间进行了实例化 插件和应用程序初始化程序。现在观察者被加载了 应用程序初始化程序,因此观察到的模型可以使用 扩展。
如果你有可能在初始化中使用观察模型 你仍然可以通过调用ModelObserver.instance来加载他们的观察者 之前。 观察者是单身,并且调用实例化和 注册它们。
http://www.rubydoc.info/gems/rails-observers/0.1.2/ActiveRecord/Observer
这应该通过一个测试来捕获,该测试在同一规范中一个接一个地保存2个对象。