From 335fcc214a4b7ea5e10b3610cce6faea4262e4f6 Mon Sep 17 00:00:00 2001 From: Genadi Samokovarov Date: Sat, 27 Feb 2016 19:23:42 +0200 Subject: Introduce Module#delegate_missing_to When building decorators, a common pattern may emerge: class Partition def initialize(first_event) @events = [ first_event ] end def people if @events.first.detail.people.any? @events.collect { |e| Array(e.detail.people) }.flatten.uniq else @events.collect(&:creator).uniq end end private def respond_to_missing?(name, include_private = false) @events.respond_to?(name, include_private) end def method_missing(method, *args, &block) @events.send(method, *args, &block) end end With `Module#delegate_missing_to`, the above is condensed to: class Partition delegate_missing_to :@events def initialize(first_event) @events = [ first_event ] end def people if @events.first.detail.people.any? @events.collect { |e| Array(e.detail.people) }.flatten.uniq else @events.collect(&:creator).uniq end end end David suggested it in #23824. --- .../active_support/core_ext/module/delegation.rb | 61 +++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) (limited to 'activesupport/lib/active_support/core_ext/module/delegation.rb') diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb index 0d46248582..a97a4add93 100644 --- a/activesupport/lib/active_support/core_ext/module/delegation.rb +++ b/activesupport/lib/active_support/core_ext/module/delegation.rb @@ -148,7 +148,6 @@ class Module # Foo.new("Bar").name # raises NoMethodError: undefined method `name' # # The target method must be public, otherwise it will raise +NoMethodError+. - # def delegate(*methods) options = methods.pop unless options.is_a?(Hash) && to = options[:to] @@ -215,4 +214,64 @@ class Module module_eval(method_def, file, line) end end + + # When building decorators, a common pattern may emerge: + # + # class Partition + # def initialize(first_event) + # @events = [ first_event ] + # end + # + # def people + # if @events.first.detail.people.any? + # @events.collect { |e| Array(e.detail.people) }.flatten.uniq + # else + # @events.collect(&:creator).uniq + # end + # end + # + # private + # def respond_to_missing?(name, include_private = false) + # @events.respond_to?(name, include_private) + # end + # + # def method_missing(method, *args, &block) + # @events.send(method, *args, &block) + # end + # end + # + # With `Module#delegate_missing_to`, the above is condensed to: + # + # class Partition + # delegate_missing_to :@events + # + # def initialize(first_event) + # @events = [ first_event ] + # end + # + # def people + # if @events.first.detail.people.any? + # @events.collect { |e| Array(e.detail.people) }.flatten.uniq + # else + # @events.collect(&:creator).uniq + # end + # end + # end + # + # The target can be anything callable withing the object. E.g. instance + # variables, methods, constants ant the likes. + def delegate_missing_to(target) + target = target.to_s + target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target) + + module_eval <<-RUBY, __FILE__, __LINE__ + 1 + def respond_to_missing?(name, include_private = false) + #{target}.respond_to?(name, include_private) + end + + def method_missing(method, *args, &block) + #{target}.send(method, *args, &block) + end + RUBY + end end -- cgit v1.2.3