Created
July 23, 2014 19:11
-
-
Save Peeja/5f662e1bf769817ec2c4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module AliasMethodChainResilient | |
# Give us a module which will intercept attempts to alias methods named in | |
# the keys of method_aliases, and instead alias the methods named in the | |
# values of method_aliases. | |
def self.alias_intercepting_module(method_aliases) | |
Module.new do | |
define_method :alias_method do |new_name, old_name| | |
if method_aliases.key?(old_name.to_sym) | |
super new_name, method_aliases[old_name.to_sym] | |
else | |
super new_name, old_name | |
end | |
end | |
end | |
end | |
def prepend_features(base) | |
method_aliases = instance_methods.each_with_object({}) do |method_name, aliases| | |
aliases[method_name] = :"__#{method_name}_before_#{self.name}" | |
base.send :alias_method, aliases[method_name], method_name | |
end | |
base.singleton_class.send :prepend, AliasMethodChainResilient.alias_intercepting_module(method_aliases) | |
super | |
end | |
end | |
module M | |
# Without this, we'll get a NoMethodError in Ruby 2.0, and a SystemStackError | |
# in 2.1. With it, things work as expected. | |
extend AliasMethodChainResilient | |
def do_it | |
puts "M" | |
super | |
end | |
end | |
class C | |
def do_it | |
puts 'C' | |
end | |
prepend M | |
def do_it_with_amc | |
puts 'amc' | |
do_it_without_amc | |
end | |
alias_method :do_it_without_amc, :do_it | |
alias_method :do_it, :do_it_with_amc | |
end | |
C.new.do_it | |
# Output, with AliasMethodChainResilient | |
# M | |
# amc | |
# C |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment