三里屯摇滚 发表于 2012-02-13 16:39

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

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




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

使用和实现如下,


Ruby代码1.class Klass   
2.def salute_with_log   
3.    puts "Calling method..."
4.    salute_without_log   
5.    puts "...Method called"
6.end
7.
8.alias_method :salute_without_log, :salute
9.alias_method :salute, :salute_with_log
10.end
11.
12.Klass.new.salute   
13.# Prints the following:   
14.# Calling method...   
15.# Aloha!   
16.# ...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代码1.module InstanceMethods   
2.def deliver_with_switchable_smtp!(mail = @mail)   
3.    unless logger.nil?   
4.      logger.info"Switching SMTP server to: #{custom_smtp.inspect}"   
5.    end
6.    ActionMailer::Base.smtp_settings = custom_smtp unless custom_smtp.nil?   
7.    deliver_without_switchable_smtp!(mail = @mail)   
8.end
9.end
10.def self.included(receiver)   
11.receiver.send :include, InstanceMethods   
12.receiver.class_eval do
13.    alias_method_chain :deliver!, :switchable_smtp
14.end
15.end
16.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代码1.class Something   
2.module Base   
3.    def my_method   
4.      # (A) original functionality   
5.    end
6.end
7.
8.module PreExtension   
9.    def my_method   
10.      # (B) before the original   
11.      super # calls whatever was my_method before this definition was made   
12.    end
13.end
14.
15.module PostExtension   
16.    def my_method   
17.      super # calls whatever was my_method before this definition was made   
18.      # (C) after the original   
19.    end
20.end
21.
22.include Base # this is needed to place the base methods in the inheritance stack   
23.include PreExtension # this will override the original my_method   
24.include PostExtension # this will override my_method defined in PreExtension   
25.end
26.
27.s = Something.new
28.s.my_method   
29.#=> this is a twice extended method call that will execute code in this order:   
30.#=> (B) before the original   
31.#=> (A) the original   
32.#=> (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代码1.
2.module PreExtension; end
3.module PostExtension; end
4.
5.include PreExtension   
6.include PostExtension   
7.end
8.
9.Something.ancestors # =>

module PreExtension; end
module PostExtension; end

include PreExtension
include PostExtension
endSomething.ancestors # =>




Ruby代码1.class SomethingNew   
2.module Base   
3.    def my_method   
4.      puts "(A)"
5.    end
6.end
7.
8.module Extension   
9.    def my_method   
10.      puts "(B)"
11.      super
12.    end
13.end
14.
15.include Base   
16.include Extension   
17.end
18.
19.SomethingNew.new.my_method   
20.# Output:   
21.# >> (B)   
22.# >> (A)   
23.
24.SomethingNew.ancestors # =>

清风鸟儿 发表于 2012-02-13 16:40

谢谢分享

2gua 发表于 2012-02-16 08:34

屯哥的这不错。

Sevk 发表于 2012-02-16 13:46

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