over 11 years ago
最近幾次上課同學都有問到 ! 與 ? 的問題。因為已經回答三次了,覺得應該足夠做懶人包。
Ruby 中的 ! 與 ?
加在 method 後面,如 empty? 或 gsub!
在 Ruby 中,method 的命名,是允許後面加一個 ! 與 ? 結尾。
一般的慣例是,如果
- 設計一個 method 後面有
?,如empty?,表示回傳值「預期」會是 (boolean)true/false。 - 如果一個 method 後面有
!,如gsub!,表示此 method 執行,「預期」會改變原物件裡面的值。
(如果你自己設計的 method,加 ? 其實不會自動轉 true / false,這只是一個「大家認為」「預期」應該的慣例)
2.0.0-p195 :001 > string = "ABC"
=> "ABC"
2.0.0-p195 :002 > string.gsub("A","a")
=> "aBC"
2.0.0-p195 :003 > string
=> "ABC"
2.0.0-p195 :004 > string.gsub!("A","a")
=> "aBC"
2.0.0-p195 :005 > string
=> "aBC"
加在變數前面,如 !current_user
! 前面表示相反值。
if !current_user:若 current_user 不存在
! 與 = 放在一起,如 !=
!= :就是 不等於
( current_user ) ? current_user.name : "Anonymous"
三元判斷式:上面這一段等於
if current_user
current_user.name
else
"Anonymous"
end
!!
!! 把該物件轉成 true 或 false
2.0.0-p195 :008 > a = "a string"
=> "a string"
2.0.0-p195 :009 > !!a
=> true
2.0.0-p195 :010 > b = nil
=> nil
2.0.0-p195 :011 > !!b
=> false
Rails 中的 ! 與 ?
save 與 save! / create 與 create!
Rails 中的這兩組 save 與 create 與行為與 Ruby 的不太一樣。
其中 save / create,遇到過 validation 時,只會回傳 true 或 false。但有時候我們要 debug 一個表單,有時候一直不知道為何表單為何沒成功一直 false,有時候會使用 save! 或 create! 去 debug。這兩個 method 會 throw ActiveRecord::RecordInvalid exception 中斷程式。明確的告訴你壞在哪邊。
Rails 4.0 以前的 method?
在 Rails 4.0 以前的版本。若你有一個 boolean attribute 叫 is_admin。你可以直接在程式碼裡面呼叫 is_admin? (不需另外包裝)就會回傳 true / false
Rails 4.1 + 這個版本的 ! 與 ?
Rails 4.1+ 內建了方便實作類 state machine 的 enum 。! 與 ? 會自動幫你變更狀態和查詢狀態。
class Conversation < ActiveRecord::Base
enum status: [ :active, :archived ]
end
# conversation.update! status: 0
conversation.active!
conversation.active? # => true
conversation.status # => "active"
# conversation.update! status: 1
conversation.archived!
conversation.archived? # => true
conversation.status # => "archived"
# conversation.update! status: 1
conversation.status = "archived"
# conversation.update! status: nil
conversation.status = nil
conversation.status.nil? # => true
conversation.status # => nil
可以看到一些微妙的差別。