Skip to content

Instantly share code, notes, and snippets.

@tisba
Created January 22, 2012 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tisba/294f56ed664efa99dcac to your computer and use it in GitHub Desktop.
Save tisba/294f56ed664efa99dcac to your computer and use it in GitHub Desktop.
RIM007 - Python-style Decorators
class BaseDecorator
def initialize(closure)
@closure = closure
end
def bind_to(receiver)
@closure = @closure.bind(receiver)
end
end
class CacheDecorator < BaseDecorator
def call(*args)
puts "Before closure"
result = @closure.call(*args)
puts "After closure"
return result
end
end
module FunctionDecorators
def self.included(receiver)
receiver.instance_eval {
def decorate(decorator)
@decorate_next_with = decorator
end
def method_added(name)
if @decorate_next_with
FunctionDecorators.apply_decorator(@decorate_next_with, name, self)
@decorate_next_with = nil
end
end
def __decorators
@_decorators ||= {}
end
}
end
def self.apply_decorator(decorator, method_name, target)
decorated_method = target.instance_method(method_name)
target.send(:remove_method, method_name)
target.__decorators[method_name] = decorator.new(decorated_method)
new_method = <<-RUBY
def #{method_name}(#{params = decorated_method.parameters.collect(&:last).join(',')})
self.class.__decorators[:#{method_name}].bind_to(self)
self.class.__decorators[:#{method_name}].call(#{params})
end
RUBY
class_eval new_method
end
end
class Object
include FunctionDecorators
end
class DBLayer
decorate CacheDecorator
def find(id)
puts "Called :find with #{id}"
puts "I am: #{self}"
end
def destroy; end
def create; end
decorate CacheDecorator
def count
puts "Called :count"
return 1337
end
end
db_layer = DBLayer.new
db_layer.find(23)
puts db_layer.count
@tisba
Copy link
Author

tisba commented Jan 22, 2012

Beispiel Code zur Anwendung von Methoden als Closures aus der ersten Ausgabe von "Ruby is Magic" zum Thema Closures in Ruby: http://rubyismagic.de/blog/2012/01/19/episode-7-closures/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment