Skip to content

Instantly share code, notes, and snippets.

@masa16
Last active May 7, 2023 18:50
Show Gist options
  • Save masa16/44ed5a8a8426fd79bef31edbf7811ed9 to your computer and use it in GitHub Desktop.
Save masa16/44ed5a8a8426fd79bef31edbf7811ed9 to your computer and use it in GitHub Desktop.
Decorator for Ruby similar to Python's decorator
module Decorator
@@decorators = []
def decorate(method_name,*args)
@@decorators << [method_name.to_sym,args]
end
def method_added(method_name)
super
return if @@decorators.empty?
decorators = @@decorators.reverse.map{|name,args| [method(name),args]}
@@decorators = []
method = instance_method(method_name)
define_method(method_name) do |*args|
decorators.inject(method.bind(self)){|m,d| d[0].call(*d[1],&m)}.call(*args)
end
end
end
require 'benchmark'
module SampleDecorator
include Decorator
def print_args
lambda{|*args|
printf "args = (%s)\n", args.map{|x| x.inspect}.join(',')
yield(*args)
}
end
def measure(label:nil)
lambda{|*args|
a = nil
Benchmark.bm do |x|
x.report(label){ a = yield(*args) }
end
a
}
end
end
class Test
extend SampleDecorator
decorate :print_args
decorate :measure,label:"mul"
def mul(a,b)
a * b
end
end
t = Test.new
p t.mul(3,4)
=begin
$ ruby decorator.rb
args = (3,4)
user system total real
mul 0.000009 0.000001 0.000010 ( 0.000004)
12
=end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment