so_brave 发表于 2012-02-04 13:22

alias_method_chain方法在3.1以后的替代使用方式

alias_method_chain方法在3.1以后的替代使用方式





alias_method_chain()
是rails里的一个广泛使用的方法,简单说,就是你要重写一个方法,在里面加上一个新方法后,还要使用同名的原方法调用。

使用和实现如下,

Ruby代码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

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再看一个
Ruby代码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
d

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就说这个事现在流行的方式怎么调:
Ruby代码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

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 originalsuper是上一个module里同名方法
include有个顺序覆盖
Ruby代码module PreExtension; end
module PostExtension; end

include PreExtension   
include PostExtension   
end

Something.ancestors # =>


module PreExtension; end
module PostExtension; end

include PreExtension
include PostExtension
end

Something.ancestors # => Ruby代码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 # =>

小忻黑夜 发表于 2012-02-04 13:22

谢谢分享
页: [1]
查看完整版本: alias_method_chain方法在3.1以后的替代使用方式