2012-03-11 55 views
2

在Ruby中是否有.?運算符,它在調用對象之前檢查對象是否爲nil。? (存在)運營商在紅寶石?

舉例來說,如果我有代碼:

if person and person.neighbor and person.neighbor.house and person.neighbor.house.rooms 
    person.neighbor.house.rooms.each do |room| 
     blah 
    end 
end 

難道還有比其如果檢查做一個在任何事情上更好的辦法?

請不要說「代碼的方式,這些對象不會永遠是nil」,我從API調用中獲取這些東西,並且無法控制它。

+1

的[得墨忒耳定律(http://en.wikipedia.org/wiki/Law_of_Demeter)可能是有趣的你,因爲你的代碼侵犯了它嚴重。 – 2012-03-12 00:05:20

+0

可能重複的[有沒有對紅寶石Groovy的鏈式屬性的等效零預防?](http://stackoverflow.com/questions/8805582/is-there-an-equivalent-null-prevention-on-chained-attributes在Groovy-in-ruby) – 2012-03-12 00:06:54

+0

@AndrewMarshal,我絕對同意。然而,我想不出一個好的方法來跟蹤我的情況下的LoD。我基本上是對第三方認證平臺(即facebook twitter等)進行API調用,並獲取一個巨大的嵌套信息對象。在這個範圍內,我只想抓取一塊信息(特別是用戶的教育歷史),這個信息深深嵌套。除非我寫出5種不同的方法,每種方法只能對其後代進行調用,否則我不得不違反LoD。也許有更好的方法? – 2012-03-12 00:12:44

回答

3

最容易做的事情是使用andand寶石,雖然也有一些其他的,很平凡的實施方案,像this,或this,或者等

+1

不知道和和,它很酷的+1 – wintersolutions 2012-03-12 00:06:08

1

你正在尋找的方法是nil?

例子:

foo.nil? 

對於一個更優雅的方式來編程的防守對抗nil值,請參閱我的question關於同一主題。例如,你可以寫:

person.neighbor.house.rooms.each do |room| 
    blah 
end 
rescue false 
+0

儘管如此,你不想拯救任意的例外。 – 2012-03-12 00:01:44

+0

@DaveNewton:如果有類似零例外的東西,請隨時編輯我的答案 – wintersolutions 2012-03-12 00:04:35

1

對於第二情況下,檢查沒有對象有方法列表或沒有,你可以使用try方法

require "active_support/core_ext/object/try" 
person.try(:neighbor).try(:house).try(:rooms).each do |room| 
    blah 
end 

還是我的try

版本
class Object 
    def try(*args, &block) 
    if args.empty? and block_given? 
     begin 
     instance_eval &block 
     rescue NameError => e 
     puts e.message + ' ' + e.backtrace.first 
     end 
    elsif respond_to?(args.first) 
     send(*args, &block) 
    end 
    end 
end 

然後,你可以做到這一點在短期的方式:

person.try{neighbor.house.rooms}.each do |room| 
    blah 
end 
1

爲什麼不

begin 
    person.neighbor.house.rooms.each do |room| 
     ... 
    end 
rescue NameError 
    ... 
end 

異常處理程序是爲處理異常提出:)所以,如果你依賴別人的代碼,你不應該阻止,而是處理你的代碼崩潰,而不是檢查一切是否正常。

5

從Ruby 2.3.0開始,&.「安全導航」運算符就是這樣做的。因此,而不是

person and person.neighbor and person.neighbor.house and person.neighbor.house.rooms

現在你可以只是做

person&.neighbor&.house&.rooms

http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/