diff options
author | Genadi Samokovarov <gsamokovarov@gmail.com> | 2016-02-27 19:23:42 +0200 |
---|---|---|
committer | Genadi Samokovarov <gsamokovarov@gmail.com> | 2016-02-27 19:26:27 +0200 |
commit | 335fcc214a4b7ea5e10b3610cce6faea4262e4f6 (patch) | |
tree | 56f70b4e0518aa5a33c30a05ad5021dc2e95c172 /activesupport/lib | |
parent | ecf6dc3dfbc0cdf1b0a86f48e030debd0f917cb6 (diff) | |
download | rails-335fcc214a4b7ea5e10b3610cce6faea4262e4f6.tar.gz rails-335fcc214a4b7ea5e10b3610cce6faea4262e4f6.tar.bz2 rails-335fcc214a4b7ea5e10b3610cce6faea4262e4f6.zip |
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.
Diffstat (limited to 'activesupport/lib')
-rw-r--r-- | activesupport/lib/active_support/core_ext/module/delegation.rb | 61 |
1 files changed, 60 insertions, 1 deletions
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 |