用ActiveRecord::Observer取代model的callback
2016-02-29 23:13:16

model的callback有什麼不好嗎?

使用model callback最大的缺點就是在測試model時,callback沒辦法關掉。每次做model的save或是destroy時,callback都會被trigger。為了避免callback內的程式被執行,勢必要用stub的方式去處理callback內的程式,這顯然是個糟糕的做法。另一個缺點就是callback有種違反單一責任設計的味道。

ActiveRecord::Observer

ActiveRecord::Observer是將model callback從model切出來放到叫做observer的class中。使用的方式與callback極度類似,官方文件( https://github.com/rails/rails-observers)有詳細的說明,這裡就不再重述。使用上要注意幾點:

  • 如果是rails3,oberver是內建在rails裡,但rails4之後被切出來放在rails-observers的gem中,所以在使用時記得要加到Gemfile中。
  • 記得要在config/application.rb中加入observer的設定,不然它不會動作。

在測試中使用observer

ActiveRecord::Observer與callback極度類似,那它的好處在哪裡呢?其實最大的好處就是可以在測試中關掉它。作法是這樣的,在spec/rails_helper.rb中加入下面的設定,將observer先全部關掉。

RSpec.configure do |config|
# ...
  config.before(:example) do
    # Disable all active record observers by default
    ActiveRecord::Base.observers.disable :all
  end
# ...
end

等需要測試observer時,再打開它。

require 'rails_helper'

RSpec.describe CourseObserver, type: :model do
  describe "after_save" do
    it "should do something after save" do
      ActiveRecord::Base.observers.enable :course_observer do
        # ... the course observer is working here ...
      end
    end
  end
end

Refs