Skip to content

Instantly share code, notes, and snippets.

@chischaschos
Created November 15, 2010 16:07
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 chischaschos/700512 to your computer and use it in GitHub Desktop.
Save chischaschos/700512 to your computer and use it in GitHub Desktop.
rubylearning.org - metaprogramming - method wrapper
module RubyLearning
module Module
WRAPPER_PREFIX = 'wrapper_'
WRAPPED_PREFIX = 'wrapped_'
def before(method, prev_option = {})
prev_option.merge!(:before => normalize_method_name(method))
end
def after(method, prev_option = {})
prev_option.merge!(:after => normalize_method_name(method))
end
def wrap(original_method, &block)
define_wrapper(yield, original_method)
alias_method_chain(original_method, "#{WRAPPER_PREFIX}#{original_method}")
end
private
def normalize_method_name(method)
class_eval do
if method.respond_to? :call
method_name = "#{WRAPPER_PREFIX}#{method}"
define_method(method_name , &method)
method_name
else
method
end
end
end
def alias_method_chain(target, feature)
class_eval do
alias_method "#{WRAPPED_PREFIX}#{target}", target
alias_method target, feature
end
end
def define_wrapper(wrappers, original_method)
class_eval do
define_method "#{WRAPPER_PREFIX}#{original_method}" do
send(wrappers[:before]) if wrappers[:before]
send("#{WRAPPED_PREFIX}#{original_method}")
send(wrappers[:after]) if wrappers[:after]
end
end
end
end
end
# rubyist.rb
class Rubyist
def initialize name
@name = name
@count = 0
end
def say!
puts 'hello'
end
end
# rubyist_with_count.rb
require 'rubyist'
require 'aliasing'
class Rubyist
extend RubyLearning::Module
def in_method
@count += 1
p "#{@name}(#{@count}) starts greeting ..."
end
wrap :say! do
#before :in_method, after(lambda { p "#{@name}(#{@count}) finished greeting ..." })
#before :in_method
#after lambda { p "#{@name}(#{@count}) finished greeting ..." }
after :in_method, before(lambda { p "#{@name}(#{@count}) finished greeting ..." })
end
end
# simple1.rb
class MyClass
def greet
puts "Hello lo yaaah!"
end
end
MyClass.new.greet # => Hello!
# simple2.rb
require 'simple1'
class MyClass
def greet_with_log
puts "Calling method..."
puts "Hello!"
puts "...Method called"
end
alias_method :greet, :greet_with_log
end
MyClass.new.greet
# => Hello!
# Calling method...
# Hello!
# ...Method called
# test_snippet.rb
require 'rubyist'
satish = Rubyist.new('Satish')
3.times{satish.say!}
puts '-' * 20
require 'rubyist_with_count'
3.times{satish.say!}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment