Disabling ActiveModel Callbacks

I published an article about disabling ActiveModel callbacks , but I'm not quite sure if this is the most beautiful way to do something like this.

Mongoid::Timestamps adds a callback before saving, which updates the updated_at field. Let's say I do not want in some cases I disable the callback as follows:

 class User # I'm using Mongoid, but this should work for anything based on # ActiveModel. include Mongoid::Document include Mongoid::Timestamps def sneaky_update(attributes) User.skip_callback(:save, :before, :set_updated_at) User.update_attributes(attributes) User.set_callback(:save, :before, :set_updated_at) end end 

skip_callback , followed by set_callback , to set the remote callback again to a bad idea? How would you do that? :)

+4
source share
3 answers

How about this?

 module Mongoid module Timestamps attr_accessor :skip_updated_at def set_updated_at_new unless self.skip_updated_at set_updated_at_org end end alias set_updated_at_org set_updated_at alias set_updated_at set_updated_at_new end end class User # I'm using Mongoid, but this should work for anything based on # ActiveModel. include Mongoid::Document include Mongoid::Timestamps def sneaky_update(attributes) self.skip_updated_at = true User.update_attributes(attributes) self.skip_updated_at = false end end 
+1
source

You can skip before saving callbacks and checks with send, for example

 user = User.new(:name=>'test') user.send(:create_without_callbacks) 
+1
source

Your current solution seems "dangerous" if the update throws an exception, then the callbacks do not return to their place, which can seriously violate any request after it. Self-modifying code is a really bad idea, if it can have constant side effects for other threads, it is a bit like using global variables.

But I have a problem, and all the time I was looking for a solution, and yours was the best that I could find so far. I think Rails might need to add a more elegant way to do this for the callback module.

0
source

All Articles