lib/dry/behaviour/black_tie.rb in dry-behaviour-0.1.1 vs lib/dry/behaviour/black_tie.rb in dry-behaviour-0.2.0

- old
+ new

@@ -1,7 +1,6 @@ module Dry - # rubocop:disable Style/VariableName # rubocop:disable Style/AsciiIdentifiers # rubocop:disable Style/MultilineBlockChain # rubocop:disable Style/EmptyCaseCondition # rubocop:disable Metrics/PerceivedComplexity # rubocop:disable Metrics/CyclomaticComplexity @@ -28,47 +27,64 @@ BlackTie.protocols[self].each do |method, *_| # FIXME: CHECK PARAMS CORRESPONDENCE HERE # receiver, *args = *args singleton_class.send :define_method, method do |receiver, *args| receiver.class.ancestors.lazy.map do |c| BlackTie.implementations[self].fetch(c, nil) - end.reject(&:nil?).first[method].(receiver, *args) + end.reject(&:nil?).first[method].(*args.unshift(receiver)) end end end def defmethod(name, *params) BlackTie.protocols[self][name] = params end + DELEGATE_METHOD = lambda do |klazz, (source, target)| + klazz.class_eval do + define_method source do |this, *args, **params, &λ| + case + when !args.empty? && !params.empty? then this.send(target, *args, **params, &λ) + when !args.empty? then this.send(target, *args, &λ) + when !params.empty? then this.send(target, **params, &λ) + else this.send(target, &λ) + end + end + end + end + def defimpl(protocol = nil, target: nil, delegate: [], map: {}) raise if target.nil? || !block_given? && delegate.empty? && map.empty? mds = normalize_map_delegates(delegate, map) Module.new do - mds.each do |k, v| - singleton_class.class_eval do - define_method k do |this, *args, **params, &λ| - case - when !args.empty? && !params.empty? then this.send(v, *args, **params, &λ) - when !args.empty? then this.send(v, *args, &λ) - when !params.empty? then this.send(v, **params, &λ) - else this.send(v, &λ) - end - end - end - end + mds.each(&DELEGATE_METHOD.curry[singleton_class]) singleton_class.class_eval(&Proc.new) if block_given? # block takes precedence end.tap do |mod| - mod.methods(false).each do |m| + mod.methods(false).tap do |meths| + (BlackTie.protocols[protocol || self].keys - meths).each_with_object(meths) do |m, acc| + safe_logger.warn("Implicit delegate #{(protocol || self).inspect}##{m} to #{target}") + DELEGATE_METHOD.(mod.singleton_class, [m] * 2) + acc << m + end + end.each do |m| BlackTie.implementations[protocol || self][target][m] = mod.method(m).to_proc end end end module_function :defimpl private + def safe_logger + if Kernel.const_defined?('::Rails') + Rails.logger + else + require 'logger' + Logger.new($stdout) + end + end + def normalize_map_delegates(delegate, map) [*delegate, *map].map do |e| case e when Symbol, String then [e.to_sym] * 2 when Array then e.map(&:to_sym) if e.size == 2 @@ -81,7 +97,6 @@ # rubocop:enable Metrics/CyclomaticComplexity # rubocop:enable Metrics/PerceivedComplexity # rubocop:enable Style/EmptyCaseCondition # rubocop:enable Style/MultilineBlockChain # rubocop:enable Style/AsciiIdentifiers - # rubocop:enable Style/VariableName end