Skip to content

Instantly share code, notes, and snippets.

@shikhalev
Created August 18, 2013 01:58
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 shikhalev/6259566 to your computer and use it in GitHub Desktop.
Save shikhalev/6259566 to your computer and use it in GitHub Desktop.
Samples for «decorators»
# encoding: utf-8
class Module
def decorator name, &wrapper
define_singleton_method name do |*names, **opts|
if names.length != 0
@ignore_wrap = true
names.each do |nm|
define_method nm, &wrapper.call(instance_method(nm), **opts)
end
@ignore_wrap = false
else
ma = method :method_added
define_singleton_method :method_added do |nm|
send name, nm, **opts unless @ignore_wrap
ma.call nm if ma
end
end
end
end
end
# encoding: utf-8
def show x, &block
puts block.call(x)
end
def alpha x
x + 1
end
a = method(:alpha)
puts a.inspect
puts a.call(0)
b = proc { |x| x + 2 }
puts b.inspect
Object.send :define_method, :beta, &b
puts beta(0)
show 10, &a
show 10, &b
show 10 do |x|
x + 3
end
# encoding : utf-8
def wrap &block
proc do |*args, &blk|
begin
result = block.call *args, &blk
$stderr.puts "OK: #{args.inspect} => #{result.inspect}"
result
rescue Exception => e
$stderr.puts "ERROR! #{args.inspect} => #{e.inspect}"
raise
end
end
end
alpha = proc { |x, y| x / y }
a = wrap &alpha
z1 = a.call 4, 2
z2 = a.call 4, 0
# encoding : utf-8
def wrap &block
proc do |*args, &blk|
begin
result = block.call *args, &blk
$stderr.puts "OK: #{args.inspect} => #{result.inspect}"
result
rescue Exception => e
$stderr.puts "ERROR! #{args.inspect} => #{e.inspect}"
raise
end
end
end
def wrap_method name
Object.send :define_method, name, &(wrap &(method name))
end
def alpha x, y
x / y
end
wrap_method :alpha
alpha 4, 2
alpha 4, 0
# encoding: utf-8
class Object
private
def wrap meth = nil, &block
func = meth || block
name = (meth && meth.name) || '<block>'
proc do |*args, &blk|
if UnboundMethod === func
func = func.bind self
end
begin
result = func.call *args, &blk
$stderr.puts "OK: #{self.inspect}.#{name}" +
" #{args.inspect} => #{result.inspect}"
result
rescue Exception => e
$stderr.puts "ERROR! #{self.inspect}.#{name}" +
" #{args.inspect} => #{e.inspect}"
raise
end
end
end
def wrap_singleton_method *names
names.each do |name|
define_singleton_method name, &wrap(method name)
end
end
end
class Module
def wrap_method *names
names.each do |name|
define_method name, &wrap(instance_method name)
end
end
end
class Fixnum
wrap_method :+, :-
end
z0 = 4 + 2
z1 = 4 - 2
def mul x, y
x * y
end
wrap_singleton_method :mul
z2 = mul 4, 2
# encoding: utf-8
class Object
private
def wrap meth = nil, &block
func = meth || block
name = (meth && meth.name) || '<block>'
proc do |*args, &blk|
if UnboundMethod === func
func = func.bind self
end
begin
result = func.call *args, &blk
$stderr.puts "OK: #{self.inspect}.#{name}" +
" #{args.inspect} => #{result.inspect}"
result
rescue Exception => e
$stderr.puts "ERROR! #{self.inspect}.#{name}" +
" #{args.inspect} => #{e.inspect}"
raise
end
end
end
def wrap_singleton_method *names
names.each do |name|
define_singleton_method name, &wrap(method name)
end
end
end
class Module
def wrap_method *names
if names.length != 0
@ignore_wrap = true
names.each do |name|
define_method name, &wrap(instance_method name)
end
@ignore_wrap = false
else
ma = method :method_added
define_singleton_method :method_added do |name|
wrap_method name unless @ignore_wrap
ma.call name if ma
end
end
end
end
class Alpha
class << self
def method_added name
puts "method_added: #{name}"
end
end
def alpha
p :alpha
end
wrap_method
def beta
p :beta
end
def gamma
p :gamma
end
end
a = Alpha.new
a.alpha
a.beta
a.gamma
# encoding: utf-8
class Fixnum
alias :mul :*
def * x
result = mul x
$stderr.puts "#{self} * #{x} = #{result}"
result
end
end
a = 10 * 2
# encoding: utf-8
$: << '.'
require 'deco'
class Alpha
decorator :echo do |unbound, prefix: 'echo: ', **opts|
proc do |*args, &blk|
puts prefix + 'name = ' + unbound.name.inspect if opts[:name]
puts prefix + 'args = ' + args.inspect if opts[:args]
result = unbound.bind(self).call *args
puts prefix + 'result = ' + result.inspect if opts[:result]
result
end
end
def alpha
:alpha
end
echo :alpha, prefix: '', result: true
end
class Beta < Alpha
def beta x
"BETA: " + x.to_s
end
echo :beta, args: true, result: true
echo args: true, name: true, result: true, prefix: '[*] '
def gamma a, b, c
a * b * c
end
end
b = Beta.new
b.alpha
b.beta 1
b.gamma 1, 2, 3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment