【Rails】presenceメソッドを使ってpresent?メソッドのコードをリファクタリングしよう!2019年10月03日Railspresenceメソッドとはpresenceメソッドを使用したオブジェクトが存在すればそのオブジェクト自身を返し、存在しなければnilを返すメソッドです。nilpresenceメソッドはActiveSupportで定義されているメソッドです。present?end上記の様に定義されており、present?がtrueの時にオブジェクト自身(self)を返します。present?がfalseの場合は、nilが返ります。''の場合はpresent?がfalseなのでnilが返ったということになります。演算子の併用する例を見ていきましょう。演算子についてまず簡単におさらいします。'numは10または50または100のうちのどれかです。numは10または50または100のうちのどれかです。演算子を使うことがよくあります。演算子は左から順番にその式がtrueであるかを判定していて、falseが出れば一つ右の式をtrueか判定して、falseが出ればまた一つ右の式をtrueか判定してと繰り返し、trueが出ればその式は真になるという考え方です。文章での説明は難しいのでコードで見て理解しましょう。'numは10または50または100のうちのどれかです。numは10または50または100のうちのどれかです。演算子は右の式に移ります。falseは真と判定されないので、scoreに10が入りました。この考え方を応用すると、オブジェクトがnilだった場合はこの値を返すということが簡潔に行えます。実際の例を見てみましょう。新規ユーザーを作成するviewのフォームから、収入の項目を空で送信した場合incomeカラム(収入)にvalidationをかけているので、エラーが起きてしまいます。下記は動画になります。0とすると、フォームで入力された値が入っていればフォームで入力した値を返し、もし空で送られていれば0を返すということができる様になります。下記は動画になります。0でフォームに入力した値を取得できます。下記は動画になります。返したい値で設定できるpresent?メソッドとの違いについてリンクをコピーしましたpresenceメソッドとpresent?メソッドの違いについて理解しましょう。falsepresenceメソッドはレシーバーの値があればレシーバーの値を返し、値がなければnilを返しました。present?メソッドは「空配列・空ハッシュ・空文字」といった器はあるけど、中身が空のものは全てfalseで返すメソッドです。数字の0でも何かしら文字が入っているとtrueを返すメソッドです。false)を返すメソッドです。この真偽値を返すメソッドをどの様にコード上で使うかみてみましょう。'stringは空文字です。'endこの様に変数に値があれば〇〇、なければ〇〇という用途でif文と併用してpresent?メソッドはよく使用します。三項演算子でもpresent?メソッドはよく使います。三項演算子について知らない人は、三項演算子を徹底解説!の記事に使い方が詳しく書いているのでご覧ください。'stringは空文字です。'三項演算子でこの様に書き換えることができます。演算子の併用した書き方で綺麗で分かりやすいコードにリファクタリングすることができます。present?メソッドをpresenceメソッドでリファクタリングしてみようリンクをコピーしましたリファクタリングする前にもう一度presenceメソッドがどの様に定義されているか見直しましょう。present?endpresenceメソッドはpresent?がtrueな場合、つまり何かしらレシーバーに値が入っていればレシーバー自体を返し、もしレシーバーが空であればnilを返すメソッドです。いう形を使うとオブジェクトがあればオブジェクトを返し、もしなければ~~を返すことが出来ると説明しました。'stringは空文字です。'stringは空文字です。'この様にリファクタリングすることができます。今回は短いコードなので、これがどれだけ簡潔になっているか分かりにくいかもしれないですが、数が多くなればなるほどより簡潔になっていることがわかります。黒色このコードを下記にリファクタリングできます。'オブジェクトはありません'この様なコードに書き換えましょう。オブジェクト3.presenceこの様にリファクタリングする様にしましょう。すればあなたの書いているコードはすごくスッキリして見やすいコードになります!ポイントpresent?を使っているif文はpresenceでリファクタリングpresent?を使っている三項演算子はpresenceでリファクタリングtryメソッドとの違いについてリンクをコピーしましたpresenceメソッドとの違いを見る前に、まずtryメソッドとはどの様なメソッドであるか知りましょう。'hogeメソッドはありません。"hogeメソッドはありません。niltryメソッドはオブジェクト.try(:メソッド名)の返り値があればその返り値を返し、もし返り値がなければnilを返すメソッドです。このメソッドの最大の特徴はnilガードが出来る点にあります。nil.try(:name)としてもエラーが出ずにnilを返すので、エラーが起きないことがtryメソッドの最大の特徴になります。オブジェクト.try(:メソッド名)があればその返り値を返し、もしなければnilを返すという点でpresenceメソッドとよく似たメソッドになります。演算子と併用できます。~~tryメソッドはnilガードが出来るので、基本的にNoMethodErrorを起こしません。存在しないメソッドを実行してもエラーが出ないので、エラーが出なくて便利と思うかもしれません。NoMethodErrorをキャッチせずにnilを出して処理するのは、エラーが起こっていることに気づかずにアプリケーションが動いているので、アプリにバグが出ているのに気付いていない可能性が非常に大きくなります。そんな時NoMethodErrorを起こした時にエラーを起こそうと作られたのが、try!メソッドになります。'hogeメソッドはありません。#<Job:0x007fea0aea33e0>この様にtry!の場合はメソッドがなかった場合nilではなくNoMethodErrorを返すのでエラーをキャッチできます。try!メソッドのもう一つ注目して欲しいポイントがnilに対してメソッドを実行した場合にはNoMethodErrorを吐かないことです。nilfind_byメソッドについて知らない方はこちらの記事を参照ください。世界で一番詳しいfind_byメソッドのいろいろな使い方この様にもし送られてきた値がDBに存在しなくてもエラーを出さずに、もし存在すればhogeメソッドを実行するということができます。nilに対しても利用できるので、NoMethodErrorをキャッチできるバージョンのtryメソッドということでかなり利便性が高くなります。"消防士は登録されておりません"この様な使い方もできます。シンプルにjobというインスタンスに指定したメソッドがないとき(Job.first.try!(:hoge)にNoMethodErrorをキャッチできるということですね。このtry!メソッドと同様の動きをする&.(ぼっち演算子)と呼ばれるものがあります。このtry!メソッドをぼっち演算子に書き換えることができるので、ぼっち演算子の動きも見てみましょう。'hogeメソッドはありません。nilこの様にぼっち演算子とtry!メソッドは同様の動きをします。個人的にぼっち演算子の方が記述が少なくてスマートに見えるのでtry!よりも&.の方がよく見かける気がします。ちなみに&.(ぼっち演算子)と呼ばれる由来は人が膝を抱えてふさぎ込んでいるように見えることからの様です。~~を併用して使用できる&.(ぼっち演算子)はtry!と同様の動きをする上記で説明した通り、try!メソッドはtryメソッドよりもエラーをキャッチできてより利便性が高くなったメソッドです。presenceメソッドと動作の違いを比べるのはtry!メソッドにして二つのメソッドがどの様に違うか見比べてみましょう。try!メソッドとpresenceメソッドを比べてみようリンクをコピーしました二つのメソッドとの違いの見比べ方ですが、下記の違いで見比べていきたいと思います。nilに対して実行した場合の返り値の違い空文字に対して実行した場合の返り値の違い速度の違いまず1のnilに対しての違いを見てみましょう。nilnilに対して実行した場合は、結果は同じですね。空文字に対して実行した場合の返り値の違いを見てみましょう。以降の職業不明ではなく元々入っている空文字が出力されています。個人的にtry!メソッドのこの動作は不便と感じていてもしnameが空であれば、職業不明と出力したいです。'職業不明'とした場合は'職業不明'を返り値に返すことができます。いった点からpresenceメソッドが便利と感じていて、個人的にはpresenceメソッドを好んで使います。送られてきたデータがDBにあるか確認して、もしなければ~~を返すということもpresenceメソッドを使うとできるので大変便利です。~~を返すという風にも書けるので、presenceメソッドの方が使い勝手が良いです。速度の違いについて最後に見比べてみましょう。@utime=0.0>]わずかにpresenceメソッドの方が早いですね!これがバッチなどで数十万回実行する様なことがあった場合、目に見える形でpresenceメソッドの方が早くなると思われます。ポイントtry!メソッド、presenceメソッド共にnilに対しての返り値はnilになる。速度はpresenceの方が早い(数十万回と実行する場合は明らかな差が出そう)try!メソッドを使っていればpresenceメソッドに書き換えられるケースが多いので、try!メソッドを使っている人はメリットの多いpresenceメソッドに書き換える様にしましょう。