日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入理解alias, alias_method和alias_method_chain

發布時間:2023/12/4 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解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

這樣我們就搞定了。 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的深入理解alias, alias_method和alias_method_chain的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。