最近在專案上常看到&.的用法,因為覺得很好奇所以特別查了一下它的用途。
在解釋&.之前,我們先從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並不存在method中,而是僅能在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&.try(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的用法
Bro next time, do in english :) I would love to check back again your blog :)
Haha, ok. Will try :)