Sha256: db37443e878153a255fc8c41be347550ba4746f88dd04a34b59d888e69caef3b

Contents?: true

Size: 1.62 KB

Versions: 1

Compression:

Stored size: 1.62 KB

Contents

require "method_decorators/version"

module MethodDecorators
  def method_added(name)
    super
    orig_method = instance_method(name)

    if    private_method_defined?(name);   visibility = :private
    elsif protected_method_defined?(name); visibility = :protected
    else                                   visibility = :public
    end

    decorators = MethodDecorator.current_decorators
    return  if decorators.empty?

    define_method(name) do |*args, &blk|
      decorators.reduce(orig_method.bind(self)) do |callable, decorator|
        lambda{|*a, &b| decorator.call(callable, *a, &b) }
      end.call(*args, &blk)
    end

    case visibility
    when :protected; protected name
    when :private;   private name
    end
  end

  def singleton_method_added(name)
    super
    orig_method = method(name)

    decorators = MethodDecorator.current_decorators
    return  if decorators.empty?

    MethodDecorators.define_others_singleton_method(self, name) do |*args, &blk|
      decorators.reduce(orig_method) do |callable, decorator|
        lambda{|*a, &b| decorator.call(callable, *a, &b) }
      end.call(*args, &blk)
    end
  end

  def self.define_others_singleton_method(klass, name, &blk)
    if klass.respond_to?(:define_singleton_method)
      klass.define_singleton_method(name, &blk)
    else
      class << klass
        self
      end.send(:define_method, name, &blk)
    end
  end
end

class MethodDecorator
  @@current_decorators = []

  def self.current_decorators
    decs = @@current_decorators
    @@current_decorators = []
    decs
  end

  def self.+@
    +new
  end

  def +@
    @@current_decorators.unshift(self)
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
method_decorators-0.9.0 lib/method_decorators.rb