lib/ruby_ext/more/callbacks.rb in ruby_ext-0.5.9 vs lib/ruby_ext/more/callbacks.rb in ruby_ext-0.5.10
- old
+ new
@@ -174,10 +174,26 @@
else
block.call if block
end
end
+ # We need to prevent callback from rinning multiple times if nested
+ # (need this for wrapping methods with callbacks to correctly call super).
+ def run_callbacks_only_once callback_name, data = {}, &block
+ set = Thread.current[callback_name] ||= {}
+ if set.include? object_id
+ block.call if block
+ else
+ begin
+ set[object_id] = true
+ run_callbacks callback_name, data, &block
+ ensure
+ set.delete object_id
+ end
+ end
+ end
+
module ClassMethods
inheritable_accessor :callbacks, {}
def set_callback callback_name, type, *executor_or_options, &block
callback_name.must_be.a Symbol
@@ -204,7 +220,28 @@
callback.conditions = opt
(self.callbacks[callback_name] ||= []) << callback
end
+ def wrap_method_with_callbacks method, callback
+ method_without_callback = :"#{method}_without_#{callback}_of_#{self.alias}"
+ if method_defined? method_without_callback
+ raise "can't wrap method #{method} with #{callback} of #{self.alias} twice!"
+ end
+
+ alias_method method_without_callback, method
+ define_method method do |*args, &block|
+ # We can't use run_callbacks, because in case of the `super`
+ # call it will be runned twice.
+ run_callbacks_only_once callback do
+ send method_without_callback, *args, &block
+ end
+ end
+ end
+
+ def wrap_with_callback callback
+ instance_methods(false).each do |method|
+ wrap_method_with_callbacks method, callback
+ end
+ end
end
end
\ No newline at end of file