开发者

ActiveRecord Global Callbacks for all Models

开发者 https://www.devze.com 2023-01-19 11:03 出处:网络
I have around 40 models in my RoR application. I want to setup a after_save callback for all models. One way is to add it to all models. Since this callb开发者_运维知识库ack has the same code to run,

I have around 40 models in my RoR application. I want to setup a after_save callback for all models. One way is to add it to all models. Since this callb开发者_运维知识库ack has the same code to run, is there a way to define it globally once so that it gets invoked for all models.

I tried this with no luck:

class ActiveRecord::Base

  after_save :do_something

  def do_something
    # .... 
  end
end

Same code works if I do it in individual models.

Thanks, Imran


You should use observers for this:

class AuditObserver < ActiveRecord::Observer      

  observe ActiveRecord::Base.send(:subclasses)

  def after_save(record)
    AuditTrail.new(record, "UPDATED")
  end
end

In order to activate an observer, list it in the config.active_record.observers configuration setting in your config/application.rb file.

config.active_record.observers = :audit_observer

Note

In Rails 4, the observer feature is removed from core. Use the https://github.com/rails/rails-observers gem.


I'm pretty late on this one, but in case someone else is using Rails 3 and finds this, then this response might help.

Some models might not be loaded when the observer is loaded. The documentation says that you can override observed_classes, and that way you can get the subclasses of active record dynamically.

class AuditObserver < ActiveRecord::Observer
  def self.observed_classes                 
    ActiveRecord::Base.send(:subclasses)    
  end
end


This seemed to work for me:

ActiveRecord::Base.after_save do
   ...
end

Is there a problem I'm not seeing?


Based on @harish's answer and in this answer (https://stackoverflow.com/a/10712838/2226338):

class AuditObserver < ActiveRecord::Observer
    Rails.application.eager_load!
    observe ActiveRecord::Base.descendants

    def after_save(record)
        ...
    end
end


This actually works pretty well for me in 2.3.8:

class AudiObserver < ActiveRecord::Observer
  observe :'ActiveRecord::Base'
  #
  # observe methods...
  #
end
0

精彩评论

暂无评论...
验证码 换一张
取 消