module MethodDecorators

An implementation of pythonish decorators in Ruby Credits: Yehuda Katz (yehudakatz.com/) github.com/wycats/ruby_decorators

Attributes

decorated_methods[RW]

Public Class Methods

extended(klass) click to toggle source
# File lib/performance_promise/decorators.rb, line 7
def self.extended(klass)
  class << klass
    attr_accessor :decorated_methods
  end
end

Public Instance Methods

decorate(klass, *args) click to toggle source
# File lib/performance_promise/decorators.rb, line 56
def decorate(klass, *args)
  @decorators ||= []
  @decorators << [klass, args]
end
method_added(name) click to toggle source
# File lib/performance_promise/decorators.rb, line 31
  def method_added(name)
    return unless @decorators

    decorators = @decorators.dup
    @decorators = nil
    @decorated_methods ||= Hash.new {|h,k| h[k] = []}

    class << self; attr_accessor :decorated_methods; end

    decorators.each do |klass, args|
      decorator = klass.respond_to?(:new) ? klass.new(self, instance_method(name), *args) : klass
      @decorated_methods[name] << decorator
    end

    class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
      def #{name}(*args, &blk)
        ret = nil
        self.class.decorated_methods[#{name.inspect}].each do |decorator|
          ret = decorator.call(self, *args, &blk)
        end
        ret
      end
    ruby_eval
  end
method_missing(name, *args, &blk) click to toggle source
Calls superclass method
# File lib/performance_promise/decorators.rb, line 13
  def method_missing(name, *args, &blk)
    if Object.const_defined?(name)
      const = Object.const_get(name)
    elsif Decorator.decorators.key?(name)
      const = Decorator.decorators[name]
    else
      return super
    end

    instance_eval <<-ruby_eval, __FILE__, __LINE__ + 1
      def #{name}(*args, &blk)
        decorate(#{const.name}, *args, &blk)
      end
    ruby_eval

    send(name, *args, &blk)
  end