`

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

阅读更多
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]

分享到:
评论
5 楼 ruby_windy 2012-02-06  
see 这个stackoverflow页:

http://stackoverflow.com/questions/3689736/rails-3-alias-method-chain-still-used
4 楼 Hooopo 2012-02-05  
是Rails里面不用这个方法了,但是还在activesupport里,没有移除。
写插件用super是不行的,还得用alias method chain.
3 楼 夜鸣猪 2012-02-05  
Hooopo 写道
什么时候移掉的?求链接。。

俺是看railscast里提到,rails开始用新的方式
http://railscasts.com/episodes/232-routing-walkthrough-part-2
这个也有提到
http://piotrsarnacki.com/2010/06/18/rails-internals-railties/
ms都不是官方声明
2 楼 Hooopo 2012-02-05  
什么时候移掉的?求链接。。
1 楼 ruby_windy 2012-02-05  
alias_method_chain并不那么清楚,移掉蛮好的.

新方法使用super,实现很ruby化~明白include的加载机制十分重要~

相关推荐

Global site tag (gtag.js) - Google Analytics