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