深入理解alias, alias_method和alias_method_chain
生活随笔
收集整理的這篇文章主要介紹了
深入理解alias, alias_method和alias_method_chain
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
對于alias, alias_method, alias_method_chain的深入理解是有益的,因為rails3的源碼里很多地方使用了alias_method_chain的魔法。 有人評論說alias_method_chain使用的過多不好,具體怎么不好,是后話了,這篇文章集中在理解這3個方法上面。
如果想轉載本文,請注明出處,謝謝!請尊重別人的勞動成果,為構建豐富web原創內容做貢獻!
1. alias
?? Ruby里的關鍵字,用于定義方法或者全局變量的別名。 例子:
?? class A
???? def m1
?????? puts "m1"
???? end
???? alias m2 m1
??? end
=> nil
a = A.new
=> #<A:0xb7ef5234>
?a.m1
m1
=> nil
a.m2
m1
=> nil
在使用的時候,注意原有的方法名在最后位置,用空格分開。
2. alias_method
作用和alias差不多,是Module的一個私有實例方法,只能用于給方法起別名,并且參數只能是字符串或者符號(alias后面跟的直接是方法名,不是字符串也不是符號)。例子:
class B
? def b
??? p "b"
? end
? alias_method :c, :b
end
=> B
b = B.new
=> #<B:0xb7ee75bc>
b.c
"b"
=> nil
b.b
"b"
=> nil
注意,alias_method的參數必須是字符串或者是符號,并且用逗號分隔。
3. alias_method_chain
是ActiveSupport的一個公有實例方法。同樣接受兩個參數,可以是符號,也可以是字符串,但要注意一下第1個參數才是原始方法(alias_method的第2個參數是原始方法)。例子:
class A
? def m1
??? puts 'm1'
? end
? def m1_with_m2
??? puts "do something befor m1"
??? m1_without_m2
??? puts "do something after m2"
? end
? alias_method_chain :m1, :m2
end
=> A
a = A.new
=> #<A:0xb7bd9820>
a.m1
do something befor m1
m1
do something after m2
=> nil
上面的代碼用alias或者alias_method也能完成:
class A ?
? def m1 ?
??? puts 'm1' ?
? end
? alias m1_without_m2 m1 ?
? def m1_with_m2 ?
??? puts 'do something else' ?
??? m1_without_m2 ?
? end ?
? alias m1 m1_with_m2 ?
end
那么其原理也一目了然了:
a = A.new
a.m1
當調用m1的時候, m1_with_m2會執行,? 在puts "do something befor m1"之后,執行m1_without_m2,這個時候是執行了真正的m1方法。 這樣就形成了一個類似于AOP的行為。
也可以說,對外把m1方法隱藏起來了,對類外部,實際上把m1_with_m2改頭換面已經成為了另一個方法,只是我們不知道而已,因為它還叫m1.
再來看看alias_method_chain的源碼:
def alias_method_chain(target, feature)?
? # Strip out punctuation on predicates or bang methods since?
? # e.g. target?_without_feature is not a valid method name.?
? aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1?
? yield(aliased_target, punctuation) if block_given???????
? with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"?
? alias_method without_method, target?
? alias_method target, with_method???????
? case?
??? when public_method_defined?(without_method)?
????? public target?
??? when protected_method_defined?(without_method)?
????? protected target?
??? when private_method_defined?(without_method)?
????? private target?
? end?
end
一個道理。
更實際的例子:
在一些rails比較老的系統里,搜索功能的日期選擇可能會用到date_select,這個方法會生成類似于這樣的頁面元素:
search_form[start_from(1i)]年
search_form[start_from(2i)]月
search_form[start_from(3i)]日
把這樣的參數傳回去,就無法查詢到對應的日期。這個時候我們需要在后臺得到查詢條件之后來處理日期,比如:
get_conditions 這個方法假如是得到頁面查詢條件的,它返回一個數組,這個時候我們可以定義:
def get_conditions_with_handle_date
? puts "你可以在get_conditions方法執行前干點別的,如果你愿意"
? get_conditions_without_handle_date
? puts "get_conditions執行完了,我們可以在其后干點別的,比如說處理日期"
? conditions.reject!{|condition|condition[0] =~ /\([1-3]i\)/}?? # 把條件數組里的1i,2i,3i之類的去掉。
? conditions << ["? <= #{@model.table_name}.created_at", @search.start_from] if @search.start_from? #給搜索對象里添加正確的查詢日期條件
? conditions << ["#{@model.table_name}.created_at < ?", @search.end_to + 1.day] if @search.end_to?? #給搜索對象里添加正確的查詢日期條件
end
? #然后實施魔法
? alias_method_chain :get_conditions, :handle_date
這樣我們就搞定了。 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
如果想轉載本文,請注明出處,謝謝!請尊重別人的勞動成果,為構建豐富web原創內容做貢獻!
1. alias
?? Ruby里的關鍵字,用于定義方法或者全局變量的別名。 例子:
?? class A
???? def m1
?????? puts "m1"
???? end
???? alias m2 m1
??? end
=> nil
a = A.new
=> #<A:0xb7ef5234>
?a.m1
m1
=> nil
a.m2
m1
=> nil
在使用的時候,注意原有的方法名在最后位置,用空格分開。
2. alias_method
作用和alias差不多,是Module的一個私有實例方法,只能用于給方法起別名,并且參數只能是字符串或者符號(alias后面跟的直接是方法名,不是字符串也不是符號)。例子:
class B
? def b
??? p "b"
? end
? alias_method :c, :b
end
=> B
b = B.new
=> #<B:0xb7ee75bc>
b.c
"b"
=> nil
b.b
"b"
=> nil
注意,alias_method的參數必須是字符串或者是符號,并且用逗號分隔。
3. alias_method_chain
是ActiveSupport的一個公有實例方法。同樣接受兩個參數,可以是符號,也可以是字符串,但要注意一下第1個參數才是原始方法(alias_method的第2個參數是原始方法)。例子:
class A
? def m1
??? puts 'm1'
? end
? def m1_with_m2
??? puts "do something befor m1"
??? m1_without_m2
??? puts "do something after m2"
? end
? alias_method_chain :m1, :m2
end
=> A
a = A.new
=> #<A:0xb7bd9820>
a.m1
do something befor m1
m1
do something after m2
=> nil
上面的代碼用alias或者alias_method也能完成:
class A ?
? def m1 ?
??? puts 'm1' ?
? end
? alias m1_without_m2 m1 ?
? def m1_with_m2 ?
??? puts 'do something else' ?
??? m1_without_m2 ?
? end ?
? alias m1 m1_with_m2 ?
end
那么其原理也一目了然了:
a = A.new
a.m1
當調用m1的時候, m1_with_m2會執行,? 在puts "do something befor m1"之后,執行m1_without_m2,這個時候是執行了真正的m1方法。 這樣就形成了一個類似于AOP的行為。
也可以說,對外把m1方法隱藏起來了,對類外部,實際上把m1_with_m2改頭換面已經成為了另一個方法,只是我們不知道而已,因為它還叫m1.
再來看看alias_method_chain的源碼:
def alias_method_chain(target, feature)?
? # Strip out punctuation on predicates or bang methods since?
? # e.g. target?_without_feature is not a valid method name.?
? aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1?
? yield(aliased_target, punctuation) if block_given???????
? with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"?
? alias_method without_method, target?
? alias_method target, with_method???????
? case?
??? when public_method_defined?(without_method)?
????? public target?
??? when protected_method_defined?(without_method)?
????? protected target?
??? when private_method_defined?(without_method)?
????? private target?
? end?
end
一個道理。
更實際的例子:
在一些rails比較老的系統里,搜索功能的日期選擇可能會用到date_select,這個方法會生成類似于這樣的頁面元素:
search_form[start_from(1i)]年
search_form[start_from(2i)]月
search_form[start_from(3i)]日
把這樣的參數傳回去,就無法查詢到對應的日期。這個時候我們需要在后臺得到查詢條件之后來處理日期,比如:
get_conditions 這個方法假如是得到頁面查詢條件的,它返回一個數組,這個時候我們可以定義:
def get_conditions_with_handle_date
? puts "你可以在get_conditions方法執行前干點別的,如果你愿意"
? get_conditions_without_handle_date
? puts "get_conditions執行完了,我們可以在其后干點別的,比如說處理日期"
? conditions.reject!{|condition|condition[0] =~ /\([1-3]i\)/}?? # 把條件數組里的1i,2i,3i之類的去掉。
? conditions << ["? <= #{@model.table_name}.created_at", @search.start_from] if @search.start_from? #給搜索對象里添加正確的查詢日期條件
? conditions << ["#{@model.table_name}.created_at < ?", @search.end_to + 1.day] if @search.end_to?? #給搜索對象里添加正確的查詢日期條件
end
? #然后實施魔法
? alias_method_chain :get_conditions, :handle_date
這樣我們就搞定了。 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的深入理解alias, alias_method和alias_method_chain的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SSH远程终端连接数问题
- 下一篇: 2010.7.27 OnDraw与On