alias_method_chain()
是rails里的一个广泛使用的方法,简单说,就是你要重写一个方法,在里面加上一个新方法后,还要使用同名的原方法调用。
使用和实现如下,
class Klass
def salute_with_log
puts "Calling method..."
salute_without_log
puts "...Method called"
end
alias_method :salute_without_log, :salute
alias_method :salute, :salute_with_log
end
Klass.new.salute
# Prints the following:
# Calling method...
# Aloha!
# ...Method called
再看一个
module InstanceMethods
def deliver_with_switchable_smtp!(mail = @mail)
unless logger.nil?
logger.info "Switching SMTP server to: #{custom_smtp.inspect}"
end
ActionMailer::Base.smtp_settings = custom_smtp unless custom_smtp.nil?
deliver_without_switchable_smtp!(mail = @mail)
end
end
def self.included(receiver)
receiver.send :include, InstanceMethods
receiver.class_eval do
alias_method_chain :deliver!, :switchable_smtp
end
end
end
就说这个事现在流行的方式怎么调:
class Something
module Base
def my_method
# (A) original functionality
end
end
module PreExtension
def my_method
# (B) before the original
super # calls whatever was my_method before this definition was made
end
end
module PostExtension
def my_method
super # calls whatever was my_method before this definition was made
# (C) after the original
end
end
include Base # this is needed to place the base methods in the inheritance stack
include PreExtension # this will override the original my_method
include PostExtension # this will override my_method defined in PreExtension
end
s = Something.new
s.my_method
#=> this is a twice extended method call that will execute code in this order:
#=> (B) before the original
#=> (A) the original
#=> (C) after the original
super是上一个module里同名方法
include有个顺序覆盖
module PreExtension; end
module PostExtension; end
include PreExtension
include PostExtension
end
Something.ancestors # => [Something, Something::PostExtension, Something::PreExtension, Object, Kernel]
class SomethingNew
module Base
def my_method
puts "(A)"
end
end
module Extension
def my_method
puts "(B)"
super
end
end
include Base
include Extension
end
SomethingNew.new.my_method
# Output:
# >> (B)
# >> (A)
SomethingNew.ancestors # => [SomethingNew, SomethingNew::Extension, SomethingNew::Base, Object, Kernel]