【Rails】try、try! 和 &.(safe navigation operator)

JiaHung Lin
4 min readApr 8, 2018

--

最近在專案上常看到&.的用法,因為覺得很好奇所以特別查了一下它的用途。
在解釋&.之前,我們先從Object#try這個method開始說起。

try

平常在寫程式的時候,我們可能會需要驗證一個object的某個method是否有值,但是有時候我們還需要事先驗證該object是否存在,所以我們會寫成

if user && user.email
# do something
end

但是這樣的寫法有點冗長,如果是在Rails中,我們可以透過try這個方法來達成相同的目的

if user.try(:email)
# do something
end

try的用法就像是Ruby中的Object#send一樣,可以讓你把method當作argument傳入object。

但是跟send不同的是,當receiving object(receiver)的該method不存在時,不會觸發NoMethodError,而是回傳nil值。

user.try(:should_be_error).try(:another_error)
#=> nil
user.send(:should_be_error)
#=> NoMethodError: undefined method `should_be_error' for #<User:0x007fca78bf5848>

try也可以搭配block使用(receiving object非nil的情況下),

User.new(email: "mail@example.com")
user.try { |u| u.email }
#=> mail@example.com

值得注意的是,try這個method並不存在Ruby中,而是僅能在Rails中使用。

try!

用法跟try相同,唯一的區別是,當傳入的argument(method)不存在時和receiving object不是nil時,會觸發NoMethodError exception,而不是nil;而當receiving object是nil值時,則會回傳nil。

user = User.new
user.try(:should_be_error).try(:another_error)
#=> nil
user.try!(:should_be_error).try(:another_error)
#=> NoMethodError: undefined method `account' for #<User:0x007fca7cf91340>
user.try!(:should_be_error).try!(:another_error)
#=> NoMethodError: undefined method `account' for #<User:0x007fca7cf91340>
user.try(:should_be_error).try!(:another_error)
#=> nil

&.(safe navigation operator)

而safe navigation operator使用起來就跟try!相似,唯一不同的點就是寫法簡潔更多,以及safe navigation operator是Ruby內建的method。

user&.(should_be_error)&.(another_error)
#=> NoMethodError: undefined method `account' for #<User:0x007fca7cf91340>

參考資料

The Safe Navigation Operator (&.) in Ruby
Safe navigation operator in Ruby
What is the difference between “try” and “&.” (safe navigation operator) in Ruby
Object#try
Object#try!
Rails中try的用法

--

--