---
# System prepended metadata

title: '\[Rails\] 什麼時候用 `present?` / `blank?` ?'

---

# \[Rails\] 什麼時候用 `present?` / `blank?` ?

## 前言 (in Ruby)

### truthy / falsy

``` ruby
if a_value
  puts 'a_value 是 truthy'
else
  puts 'a_value 是 falsy'
end
```

``` ruby
all_falsy_values_in_ruby = [nil, false]
```

### #nil?

``` ruby
nil.nil? # true
false.nil? # false
```

``` ruby
value = a_method_that_reutrn_something_or_nil_but_not_false

puts '跟下面等價' if value
puts '跟上面等價' unless value.nil?
```

## Rails

``` ruby
require "active_support"
require "active_support/core_ext/object/blank"

common_blank_things = [
  nil,
  false,
  [],
  {},
  '',
]
# 看原始碼可以得到更詳細資訊
# https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/blank.rb

# 這些類型其實都有原本的檢查方法
nil.blank? == nil.nil?
false.blank? == !false
[].blank? == [].empty?
{}.blank? == {}.empty?
''.blank? == ''.empty?

# 但
' '.blank? != ' '.empty?
```

## 所以什麼時候用？

### 1. 檢查字串是否帶有資訊的時候用

``` ruby
a_string = 'qwertyuiop'
send_message(a_string) if a_string.present?
raise 'no information!' if a_string.blank?
```

### 2. 檢查一個不確定型態的物件是否帶有資訊

#### 典型例子 Controller Params

``` ruby
params[:data].present?
```

一個 endpoint 只要 client 端能通過驗證
它可以不透過系統的前端應用直接傳送任何內容的 request 到 server 上
所以在這個例子下 `params[:data]` 可能是 `NilClass`, `Hash`, `Array`, `String`, `Number` ...

## 這些時候並不需要

1. Rails model find 只會回傳 record 或 nil
``` ruby
record = Model.find(id)
if record
  record.do_something
end
```

2. Rails has_many 只會回傳 array like 不會回傳 nil

3. 明確知道型別的時候
``` ruby
array = []
things.each do |thing|
  array << thing if thing.good?
end
puts 'it is empty' if array.empty?
puts 'have some' if array.any?
```
``` ruby
hash = {}
things.each do |thing|
  hash[thing.id] = thing if thing.good?
end
puts 'it is empty' if hash.empty?
puts 'have some' if hash.any?
```