どなブロ

Ruby, Rails, その他気になったこととか思ったこととか

【Rails】ActiveSupportのpresence

RailsActiveSupportのpresenceがええ感じです。
文字列のnilとか空白を判別して何か固定値入れたい時とか。
object.presenceって感じに書いて、objectが空だったらnilを、そうでなければobject自身を返すってやるです。

使い方とか

ドキュメントのサンプルコードを引用するとこんな感じです。
https://api.rubyonrails.org/classes/Object.html#method-i-presence

# こう書いてたのが
state   = params[:state]   if params[:state].present?
country = params[:country] if params[:country].present?
region  = state || country || 'US'

# こう書ける
region = params[:state].presence || params[:country].presence || 'US'

自分は新しくなんかのモデルのインスタンスを作る時に、
必須のカラムに対して入れるべき物が無くて別のを入れる、みたいな時に使いました。
(言葉で書くとわけわからんな・・)

例えばUserモデルがあって、name属性が必須とします。

class User
  ~~
  validates :name, presence: true
  ~~
end

それに対して、例えばどっかのSNSアカウントから情報取ってUserを作ろうとした時に、
表示名が空でアカウントIDしか無いみたいなパターンがあったとします。

そうした時にただ表示名だけ入れようとすると作れないので

# res => SNSから取った情報

puts res.name
# => nil

user = User.new(name: res.name)
user.save!
# validation通らずsaveできない

代わりにアカウントIDを入れてあげよう、みたいな時に使えます。

puts res.name
# => nil
puts res.account_id
# => "hogehoge"

user = User.new(name: res.name.presence || res.account_id)
user.save!
# OK

presence使わずに書こうとするとこんな感じですね。

user = if res.name.present?
         User.new(name: res.name)
       else
         User.new(name: res.account_id)
       end

短くなってよいかと思います〜。

中身

中身はこんな感じでした。

https://github.com/rails/rails/blob/09a2979f75c51afb797dd60261a8930f84144af8/activesupport/lib/active_support/core_ext/object/blank.rb#L45

def presence
  self if present?
end

objectが空もしくはnilか判断してtrue/false返すpresent?使って
trueならobject自身を、falseならnilを返す、という
冒頭で説明した通りの内容ですね。