ActiveRecord Global Callbacks for all Models
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
精彩评论