如何调试:Rails after_commit似乎没有被解雇?

时间:2014-11-17 09:44:05

标签: ruby-on-rails callback observers

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

1 个答案:

答案 0 :(得分:1)

请勿在Observers上使用实例变量。它们是单例,因此在观察其他对象时实例变量仍然存在。

  

加载观察者在他们观察到的模型类中注册自己,   因为它是在发生事件时通知他们的类。如   副作用,当观察者加载其相应的模型时   加载了类。

     

最多(包括)Rails 2.0.2观察者之间进行了实例化   插件和应用程序初始化程序。现在观察者被加载了   应用程序初始化程序,因此观察到的模型可以使用   扩展。

     

如果你有可能在初始化中使用观察模型   你仍然可以通过调用ModelObserver.instance来加载他们的观察者   之前。 观察者是单身,并且调用实例化和   注册它们。

http://www.rubydoc.info/gems/rails-observers/0.1.2/ActiveRecord/Observer

这应该通过一个测试来捕获,该测试在同一规范中一个接一个地保存2个对象。