Module: Kernel

Defined in:
lib/decoor.rb

Overview

System module, for global functions.

Instance Method Summary collapse

Instance Method Details

#decoor(origin, attrs = {}) { ... } ⇒ Object

Decorates an object by creating a proxy that delegates method calls to the original object.

This function creates a decorator pattern implementation that allows transparent delegation to an origin object while optionally adding additional behavior through a block.

When called with a block, it creates a new anonymous class that wraps the origin object and evaluates the block in the context of that class, allowing additional methods to be defined.

When called without a block from within a class definition, it sets up method_missing to delegate calls to the specified instance variable.

Examples:

Decorating an object with additional behavior

decorated = decoor(original_object, {cache: {}}) do
  def cached_result
    @cache[:result] ||= @origin.expensive_operation
  end
end

Setting up delegation within a class

class MyClass
  def initialize(collaborator)
    @collaborator = collaborator
  end
  decoor :collaborator
end

Parameters:

  • origin (Object, Symbol)

    The object to be decorated (when block given) or the name of an instance variable to delegate to (when no block given)

  • attrs (Hash) (defaults to: {})

    Optional attributes to be set as instance variables on the decorator (only used when block is given)

Yields:

  • Block to be evaluated in the context of the decorator class, allowing additional methods to be defined

Returns:

  • (Object)

    The decorated object (when block given) or nil (when no block given)

Author:

Since:

  • 0.1.0



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/decoor.rb', line 44

def decoor(origin, attrs = {}, &)
  if block_given?
    c = Class.new do
      def initialize(origin, attrs)
        @origin = origin
        # rubocop:disable Style/HashEachMethods
        # rubocop:disable Lint/UnusedBlockArgument
        attrs.each do |k, v|
          instance_eval("@#{k} = v", __FILE__, __LINE__) # @foo = v
        end
        # rubocop:enable Style/HashEachMethods
        # rubocop:enable Lint/UnusedBlockArgument
      end

      def method_missing(*args)
        @origin.__send__(*args) do |*a|
          yield(*a) if block_given?
        end
      end

      def respond_to?(_mtd, _inc = false)
        true
      end

      def respond_to_missing?(_mtd, _inc = false)
        true
      end
    end
    c.class_eval(&)
    c.new(origin, attrs)
  else
    class_eval("def __get_origin__; @#{origin}; end", __FILE__, __LINE__) # def _get; @name; end
    class_eval do
      def method_missing(*args)
        o = __get_origin__
        o.send(*args) do |*a|
          yield(*a) if block_given?
        end
      end

      def respond_to?(_mtd, _inc = false)
        true
      end

      def respond_to_missing?(_mtd, _inc = false)
        true
      end
    end
  end
end