「presence」を知ると「present?」で実装したコードをリファクタリングしたくなる問題(Rails)

f:id:ryoutaku_jo:20190726230132p:plain

【結論】

  • presenceメソッドとは、RailsActiveSupportによって提供されるObjectクラスのメソッド。

  • レシーバーがnilの場合はfalseを返し、nili以外の場合はレシーバーを返す。

  • 存在の有無を判定してからオブジェクトを返す条件式を書く場合h、present?より簡潔にコードが書ける

【目次】

【本題】

presenceメソッドについて

presenceメソッドとは、ActiveSupportによって提供されるRailsのメソッドです。

Objectクラスのメソッドなので、全てのオブジェクトに対して実行する事が出来ます。

レシーバーがnilや空の文字列/配列の場合はfalseを返し、nili以外の場合はレシーバーを返すという働きをします。

なお、Railsでは他にもpresent?という同じ様にオブジェクトの有無を判定して、trueかfalseを返すメソッドが存在し、そちらの方が広く使われている傾向にあります。

しかし、presenceの方が可読性が高まるシーン多くあるので、今回はそれを紹介します。

「presence」と「present?」の比較

例えば、名前が存在する場合は名前を出力し、無い場合には無記名と返す式が書く場合、present?を利用すると以下の様になります。

# nameが空文字だとfalseとなり、falseの時の処理が実行される(無記名を返す)
name = ''
name.present? ? name : '無記名'
=> "無記名"

# nameに文字が在るとtrueとなり、trueの時の処理が実行される(nameを返す)
name = '山田'
name.present? ? name : '無記名'
=> "山田"

これをpresenceメソッドで書き換えると、以下の様になります。

# nameが空文字だとname.presenceはfalseとなり、'無記名'を返す
name = ''
name.presence || '無記名'
=> "無記名"

# nameに文字が在るとname.presenceを返す
name = '山田'
name.presence || '無記名'
=> "山田"

こちらの方がコードがシンプルになりました!

Rubynilかfalse以外のオブジェクトは全て真(true)なので、name.presenceが無い(false)の場合、文字列の '無記名'がtrueとなり、それをそのまま返します。

||演算子は、左辺がtureの場合、右辺は評価されないので、name.presenceが存在すれば、name.presenceだけを返します。

条件が増えるほど恩恵が大きい

これだけだと、恩恵が少ない様に見えますが、条件が増えると、その恩恵は大きくなります。

以下は条件を増やしたコードです。

#presenceで実装する場合
price1.presence || price2.presence || price3.presence || 100

#present?で実装する場合
if price1.present?
  price1
elsif price2.present?
  price2
elsif price3.present?
  price3
else
  100
end

この様に、presenceメソッドの方が見通しが良い事が分かります。

オブジェクトの有無の判定は、多くの場面で用いると思いますので、ぜひ活用して行きたいです。

参考情報

present - リファレンス - - Railsドキュメント

Rails: `present?`より便利なActiveSupportの`presence`(翻訳)

Railsのpresenceメソッドが便利

《今日の学習進捗(3年以内に10000時間に向けて)》

社内勉強会にて、ユーザーストーリーマッピングについて学んだ。ビズ側や他の開発メンバーと、仕様について認識合わせが上手くいかないことに課題を感じていたので、非常に参考になった。

これまでは、手戻りを最小限にする為に、開発に取り組む前に要件を細かく箇条書きで洗い出し、それを道しるべに開発に取り組んでいた。しかし、考慮すべき仕様の抜け漏れが発生したりと上手く機能しない場面が多かったので、それの解決策になりそうだと考えている。

また、ユーザーストーリーマッピングとは少し離れるが、ユーザーストーリマッピングの形式で、開発進捗ごとにバックログを分けて管理する手法に転用するのも良いと感じた。 ガントチャートだと進捗状況(遅延/前倒し)が視覚的に分かりやすいが、タスクの優先順位/依存関係や現在着手中のタスクがどれか?というのが分かりづらいのが難点だと感じていたので、ぜひ取り入れたい。

管理ツールについては、「Trello」が以前使った時に非常に使いやすかった記憶があるので、個人的にそちらの方を試してみて、もし良さそうならチームに展開したい。

学習開始からの期間 :231日
今日までの合計時間:2229h
一日あたりの平均学習時間:9.7h
今日までに到達すべき目標時間:2110h
目標との解離:119h
「10,000時間」まで、

残り・・・「7771時間!」