2013-04-03 18 views
39

是否存在一些隱藏的Ruby/Rails-只有在存在時才調用方法的魔法?只有存在調用方法

可以說,我想打電話給

resource.phone_number 

但我不事先知道,如果資源響應phone_number。做到這一點的一種方法是

resource.phone_number if resource.respond_to? :phone_number 

如果在錯誤的地方使用,這並不是那麼漂亮。我很好奇,如果有什麼東西存在,更符合try的使用方式(resource.try(:phone_number))。

+0

作爲一個極端的例子,我建議在這種情況下覆蓋Object的'method_missing'來返回'nil'。這是調試的恐怖。有些人會認爲它是不好的風格,元和不必要的。 – User

+0

@用戶b,根本不是一個hor 0123。您只需將一個堆棧重新回到無例外的地方:-) – mudasobwa

+4

使用'respond_to'是最好的選擇 – apneadiving

回答

28

如果沒有與該標準的Ruby語法不滿意,您可以自由:

class Object 
    def try_outside_rails(meth, *args, &cb) 
    self.send(meth.to_sym, *args, &cb) if self.respond_to?(meth.to_sym) 
    end 
end 

現在:

resource.try_outside_rails(:phone_number) 

將表現爲你想要的。

+3

您正在覆蓋Rails中現有的'try'方法 – apneadiving

+0

Ruby可能相當棒。這不足以讓我需要爲它定義一個我自己的方法,我只是想知道它是否已經存在一個方法。 – Frans

+1

@apneadiving誰談論過Rails? – mudasobwa

10

我知道這是很舊的帖子。但只是想知道這是否可能是一個可能的答案,並且影響是否相同。

resource.try(:phone_number) rescue nil 

感謝

+3

使用Rails 4你甚至不需要'rescue':http://api.rubyonrails.org/classes/Object.html#method-i-try –

+8

'try'方法不是檢查一個方法存在,這是關於保護你免受無。例如。 'nil.try(:some_method)'將返回nil而不是引發異常,但是'valid_reference.try(:non_existant_method)'仍然會失敗(除非像你一樣,添加'rescue nil')。 – neuronaut

+1

在正常的程序流程中使用救援並不是一個好習慣。投擲和捕捉異常增加了程序的開銷。 – Josh

4

在Ruby 2.3.0(這仍然是在預覽了這一點)開始,你可以使用新的safe navigation operator

resource&.phone_number 

此外,如果任何人都對選擇的語法感興趣,我鼓勵你檢查Ruby的問題跟蹤系統中的feature request討論。我也在我的回答here中解釋了推理。

+0

操作符是否檢測方法是否被定義,或者檢查對象是否不是零? –

+0

不,AFAIK它只檢查第一個語句是否爲_nil_,如果是,則它將全部評估爲_nil_。如果未定義後續方法,則會像正常調用一樣拋出。我會尋找來源。 –

+0

根據我讀取MRI源的能力非常有限來判斷,它看起來像我假設正確。差異可以在[這裏]看到(https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/52214/diff)(需要登錄)。如果_nil_被評估,那麼實現似乎跳過下一個調用。 –

0

如果A.c已定義,並且A.aA.b不是,那麼您可以執行A.a rescue A.b rescue A.c,它會像魅力一樣工作。雖然你會打破一些愚蠢的規則。

相關問題