lib/receptacle/method_delegation.rb in receptacle-0.2.0 vs lib/receptacle/method_delegation.rb in receptacle-0.3.0

- old
+ new

@@ -24,10 +24,12 @@ # @return [void] def __build_method(method_name) method_cache = __build_method_call_cache(method_name) if method_cache.wrappers.nil? || method_cache.wrappers.empty? __define_shortcut_method(method_cache) + elsif method_cache.arity.abs > 1 + __define_full_method_high_arity(method_cache) else __define_full_method(method_cache) end end @@ -55,59 +57,82 @@ define_singleton_method(method_cache.method_name) do |*args, &inner_block| method_cache.strategy.new.public_send(method_cache.method_name, *args, &inner_block) end end - # build method to mediate method calls to strategy with full wrapper support + # build method to mediate method calls of arity 1 to strategy with full wrapper support # @param method_cache [MethodCache] method_cache of the method to be build # @return [void] def __define_full_method(method_cache) define_singleton_method(method_cache.method_name) do |*args, &inner_block| __run_wrappers(method_cache, *args) do |*call_args| method_cache.strategy.new.public_send(method_cache.method_name, *call_args, &inner_block) end end end + # build method to mediate method calls of higher arity to strategy with full wrapper support + # @param method_cache [MethodCache] method_cache of the method to be build + # @return [void] + def __define_full_method_high_arity(method_cache) + define_singleton_method(method_cache.method_name) do |*args, &inner_block| + __run_wrappers(method_cache, args, true) do |*call_args| + method_cache.strategy.new.public_send(method_cache.method_name, *call_args, &inner_block) + end + end + end + # runtime method to call before and after wrapper in correct order # @param method_cache [MethodCache] method_cache for the current method # @param input_args input parameter of the repository method call + # @param high_arity [Boolean] if are intended for a higher arity method # @return strategy method return value after all wrappers where applied - def __run_wrappers(method_cache, input_args) + def __run_wrappers(method_cache, input_args, high_arity = false) wrappers = method_cache.wrappers.map(&:new) - args = if method_cache.skip_before_wrappers? - input_args - else - __run_before_wrappers(wrappers, method_cache.before_method_name, input_args) - end - ret = yield(args) + args = + if method_cache.skip_before_wrappers? + input_args + else + __run_before_wrappers(wrappers, method_cache.before_method_name, input_args, high_arity) + end + ret = high_arity ? yield(*args) : yield(args) return ret if method_cache.skip_after_wrappers? - __run_after_wrappers(wrappers, method_cache.after_method_name, args, ret) + __run_after_wrappers(wrappers, method_cache.after_method_name, args, ret, high_arity) end # runtime method to execute all before wrappers # @param wrappers [Array] all wrapper instances to be executed # @param method_name [Symbol] name of method to be executed on wrappers # @param args input args of the repository method + # @param high_arity [Boolean] if are intended for a higher arity method # @return processed method args by before wrappers - def __run_before_wrappers(wrappers, method_name, args) + def __run_before_wrappers(wrappers, method_name, args, high_arity = false) wrappers.each do |wrapper| next unless wrapper.respond_to?(method_name) - args = wrapper.public_send(method_name, args) + args = if high_arity + wrapper.public_send(method_name, *args) + else + wrapper.public_send(method_name, args) + end end args end # runtime method to execute all after wrappers # @param wrappers [Array] all wrapper instances to be executed # @param method_name [Symbol] name of method to be executed on wrappers # @param args input args to the strategy method (after processing in before wrappers) # @param return_value return value of strategy method + # @param high_arity [Boolean] if are intended for a higher arity method # @return processed return value by all after wrappers - def __run_after_wrappers(wrappers, method_name, args, return_value) + def __run_after_wrappers(wrappers, method_name, args, return_value, high_arity = false) wrappers.reverse_each do |wrapper| next unless wrapper.respond_to?(method_name) - return_value = wrapper.public_send(method_name, return_value, args) + return_value = if high_arity + wrapper.public_send(method_name, return_value, *args) + else + wrapper.public_send(method_name, return_value, args) + end end return_value end end end