iT邦幫忙

DAY 8
2

Ruby on Rails 花招百出系列 第 9

Ruby code整理系列 ||= 的使用

本篇簡單說明以下:

  • 利用||=符號將if邏輯簡化

  • 相似的用法

  • Hash當中使用||符號的例外情況

1. 情境:檢查tag是否存在

假如今天我們在發佈post時,需要檢查作者是否有預設的tag,沒有的話就標記為"untagged":

before_save :assign_tag

def assign_tag
	self.tag = "untagged" unless defined?(self.tag)
end

上方的邏輯簡單解釋,就是先判斷tag有沒有在post的創建過程中宣告過了,如果沒有,就將tag的內容指定為"untagged";如果有宣告過的話,這邊就當作什麼都沒發生,使用原本作者指定的值。

2. 簡化

這樣的邏輯只剩一行了,還可以怎麼簡化呢?重點在於這樣的句法唸起來有點繞口,而且self.tag出現了兩次。在邏輯的處理上其實可以更進一步簡化:

def assign_tag
	self.tag ||= "untagged"
	# 或者...
	self.tag || self.tag = "untagged"
end

再次印證了『沒有最簡單,只有更簡單』的概念,第一個方法中間的||= 符號大部分英文稱作 double pipeline equal 或 or equal,中文我目前尚未看到統一的稱呼,還請強者補充。 這樣的寫法邏輯說明:回傳||左邊的值,但假如左邊回傳nil或false,改成把右邊的值指定給左邊,並回傳。第二種方法邏輯相同,但在這裡不比第一種直覺,僅供參考。 當然,既然是Rails,也可以利用Rails的ActiveRecord來解,可以在migration裡加上:default => "untagged"讓tag欄位在儲存時若沒有指定也會有default值。

3. 其他類似的or(||)用法

另一個相似的寫法如下:

result = a || "a exists" 

這樣的寫法等於:

if defined?(a)
	result = a
else
	result = "a exists"
end

不過要注意的是,由於要判斷a是否存在,所以a一定是要宣告過的數值(例如 a = nil),否則會出現NoMethodError,不像 ||= 的用法不需要先宣告。

4. Hash的例外情況

大家應該都知道以下用法:

a = Hash.new(10)

在括弧內的值,代表任何該Hash內尚未宣告的預設值,但並不會儲存起來,使用情況如下:

#以下指令在rails console照順序執行

a
# => {}

a[:number]
# => 10

a
# => {}

a[:number] = 25
# => 25

a
# => {:number => 25}

如果隨便使用hash當中的一個key,則出現的value就是預設值,但並不會儲存。除非我們使用宣告的方式進行指定,該key與value才會儲存起來。 不過,套用剛剛的or(||)用法,會看到以下的例外狀況:

a = Hash.new(10)
# => {}

a[:number] = a[:number] || 25
# => 10

a
# => {:number => 25}

在第二個步驟,有一個指定的預設value是10,於是hash就把這個value儲存起來。說實在,會遇到這樣的例外狀況應該非常少,不過假如真的很不幸在這種地方卡關,千萬要記得有這個情況喔!

延伸閱讀

Ruby Inside


上一篇
Rails code 整理系列 - Service Object 初探
下一篇
Rails新手易混淆的變數使用
系列文
Ruby on Rails 花招百出32

尚未有邦友留言

立即登入留言