提交 335fcc21 编写于 作者: G Genadi Samokovarov

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.
上级 ecf6dc3d
* Introduce Module#delegate_missing_to
When building a decorator, a common pattern emerges:
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
*Genadi Samokovarov*, *DHH*
## Rails 5.0.0.beta3 (February 24, 2016) ##
* Deprecate arguments on `assert_nothing_raised`.
......
......@@ -148,7 +148,6 @@ class DelegationError < NoMethodError; end
# 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 @@ def delegate(*methods)
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
......@@ -83,6 +83,20 @@ def type
end
end
DecoratedTester = Struct.new(:client) do
delegate_missing_to :client
end
class DecoratedReserved
delegate_missing_to :case
attr_reader :case
def initialize(kase)
@case = kase
end
end
class Block
def hello?
true
......@@ -316,6 +330,14 @@ def test_delegation_with_method_arguments
assert has_block.hello?
end
def test_delegate_to_missing_with_method
assert_equal "David", DecoratedTester.new(@david).name
end
def test_delegate_to_missing_with_reserved_methods
assert_equal "David", DecoratedReserved.new(@david).name
end
def test_parent
assert_equal Yz::Zy, Yz::Zy::Cd.parent
assert_equal Yz, Yz::Zy.parent
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册