【Rails入門説明書】present?について解説
はじめに
Railsに限らず、変数の状態を確認して、処理を分岐するのは、プログラムの常套手段で、あちこちに多用されています。
つまり、プログラムを作るために必須の知識といえるでしょう。
今回は、そんな「変数の状態を確認する」メソッドの1つ、present?メソッドについて、詳しく解説いたします。
present?メソッドとは
present?メソッドは、変数に有効な値が格納されていることを確認するメソッドです。 メソッド名に「?」が入っていますので、戻り値は真偽値で、変数に有効な値が入っていればtrue、そうでなければfalseが戻ってきます。 なお、ここでいう「有効な値」というのは、以下のような、空白文字、無効値, 偽, 空データではない場合を指します。
空白文字 | ” “ |
無効値 | nil |
偽 | false |
空データ | “” [] |
present?メソッドの基本的な構文は、以下のようになっています。
オブジェクト.present?
オブジェクトからpresent?メソッドを利用することで、そのオブジェクトに有効な値が格納されていればtrue、そうでなければfalseが返ってくるわけです。
present?メソッドの使いどころ
真偽値が返ってくるメソッドですので、ifの条件として使われることがほとんどです。しかし、ただ「ifで使われる」というだけではありません。
present?メソッドで確認するのは、「有効な値」かどうかですので、「プログラムの実行中に代入される変数の値を確認し、有効な値が代入されているときに何らかの処理をしたい」場合に使うことになるのです。
そういった場合に使うことで、プログラムの流れがつかみやすくなり、第三者や数年後の自分が困ることがなくなるのです。
なお、逆に「変数が有効な値ではない場合に、何らかの処理をしたい」という場合でも、present?メソッドを利用して処理を分岐することは可能です。
しかし、その場合、判定結果がfalseの場合に主な処理を記載することになるため、第三者がプログラムを読むときに、プログラムコードから制作者の意図を読み取りにくくなるのです。
つまり、present?メソッドは、ただ「変数が「有効な値」かどうかを確認をして分岐させる処理」で使うというわけではなく、「変数が「有効な値」であるときに何らかの処理をする」というプログラムの流れ(プログラマーの意図)を表すために利用するのが、本当の使いどころなのです。
“未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー
present?メソッドを使ってみよう
では、具体的に、present?メソッドを使って、動作確認していきましょう。
環境構築
意外にも、present?メソッドはRails独自のメソッドですので、動作確認をするためには、Rails環境が必要です。
ただし、ここでは、rails console上で、メソッドの動作を確認するだけで、特にテーブルを扱うわけでもありません。そのため、すでにRails環境がある人は、その環境上でrails consoleを起動してもかまいません。
テストできる環境がない人は、以下のコマンドで環境を作って、rails consoleを起動しましょう。
[bash]rails new present_test
cd present_test
rails c
[/bash]
present?メソッドを動かす
では、いろいろなデータを格納した変数で、present?メソッドを使った結果を確認しましょう。
(ここからのコマンド入力は、rails console上でのコマンドや表示です)
無効値と数値
[bash]a = nil
a.present?
=> false
b = 123
b.present?
=> true
[/bash]
nilは無効値ですのでfalse、数値の123は有効な値ですのでtrueとなります。
値が代入されていればtrue、nil(無効値)の場合はfalseが返ってきています。present?メソッドは、有効な値が入っている場合に処理を行いたい場合に使いますので、もっとも自然な結果です。
真偽値
[bash]c = true
c.present?
=> true
d = false
d.present?
=> false
[/bash]
真偽値が入っている変数cと変数dに対してpresent?メソッドを使うと、それぞれ同じ真偽値が返ってきます。少し混乱するかもしれませんが、これは同じ値が返ってきているわけではなく、present?メソッドの判定の結果として、「cにtrueという有効な値が格納されている」から、trueを返している(dはその逆)ということです。
文字列
[bash]e = “abc”
e.present?
=> true
f = ” “
f.present?
=> false
g = “”
g.present?
=> false
[/bash]
文字列については、「空文字列と空白文字、以外」が「有効な値」ですので、変数eのみtrueが返ってきています。(fは空白文字、gは空文字列)
もちろん、プログラムによっては、空白文字や空文字列を有効な値と扱うことはあるかもしれません。しかし、大前提として、Railsが扱っているのがデータベースであることを思い出してください。
データベースに格納されるデータは、空白文字や空文字列を有効な値として格納することはほとんどありません。そのため、プログラムコードの再利用性(他の環境でも利用する)を考慮すると、空白文字や空文字を有効な値として扱わない方が望ましいでしょう。
配列
[bash]h = [123]
h.present?
=> true
i = []
i.present?
=> false
j = [“”]
j.present?
=> true
k = [nil]
=> [nil]
k.present?
=> true
[/bash]
配列については、少し気を付けなければいけません。
配列の場合は、要素が1つでもあれば(それが空文字列やnilであっても)、present?メソッドはtrueを返してきています。
これは、present?メソッドが「配列そのもの」に対して有効かどうかを確認しているため、空データでなければ(要素があれば)有効な値であると見なしているわけです。
そのため、以下のように配列の要素でpresent?メソッドを利用した場合は、想定通り「有効な値である場合だけ」trueを返しています。
[bash]h[0].present?
=> true # h[0] = 123
i[0].present?
=> false # i[0] = nil
j[0].present?
=> false # j[0] = “”
k[0].present?
=> false # k[0] = nil
[/bash]
https://web-camp.io/magazine/archives/12654
present?メソッドと同じようなメソッドたち(defined?、nil?、empty?、blank?、presence)
present?メソッドは有効な値かどうかを判定するメソッドです。しかし、Rails(Ruby)には、同様に変数の状態を確認するメソッドが、他にも用意されています。
present?メソッドも含めて、以下の6つです。
メソッド名 | 説明 | Ruby or Rails |
---|---|---|
defined? | 変数が定義されているかどうかを判定する | Ruby |
nil? | nilかどうかを判定する | Ruby |
empty? | 空データかどうかを判定する | Ruby |
blank? | 有効な値ではないことを確認する | Ruby |
presence | 有効な値であることを確認し、有効な値であればその値を返す | Rails |
present? | 有効な値であることを確認する | Rails |
これらのメソッドを適切に使いこなせば、分岐処理をシンプルにし、同時にプログラマーの意図をプログラムそのものに組み込むことができるのです。
各メソッドの説明
では、present?メソッド以外について、簡単に説明していきましょう。
まず、基本的な構文ですが、すべてのメソッドは、状態を確認したいオブジェクトから利用するだけで、原則として引数はありません。戻り値は、presenceメソッド以外は、trueかfalseを返します。(presenceは、true/falseではなく、オブジェクトの値/nilを返します)オブジェクト.defined?
オブジェクト.nil?
オブジェクト.empty?
オブジェクト.blank?
オブジェクト.presence
defines?
ローカル変数自体が定義されているかどうかを確認するためのメソッドです。
定義されていないローカル変数を使用すると、例外が発生します。そのため、ローカル変数をプログラム内で動的に生成している処理の中では、必須といえるメソッドでしょう。
Rubyで定義されているメソッドです。
nil?
変数がnilだった場合にtrueを返すメソッドです。
定義しただけで1度も代入されていない変数はnilになっています。また、検索してデータを取得する処理などでは、対象が見つからなかった場合などはnilが返されることが多く、nilになっている変数は、プログラムの中に必ず存在します。
特に、配列などのデータ列の中の一部だけがnilである場合などは、意図せずその変数を参照してしまうことをありますので、nil?メソッドで確認して、nilなら代入するなどの処理をしておくべきでしょう。
Rubyで定義されているメソッドです。
empty?
変数が空データだった場合にtrueを返すメソッドです。
文字列や配列を扱う場合、初期状態では、空文字や空の配列であることは少なくありません。また、データを取得して配列に格納する処理の場合、nilではなく空の配列を返してくる場合もあるでしょう。
もちろん、Railsのフォームでは、空欄で確定した場合は自動で何らかのデータを入力するようなUIもあります。
そういった場合に、空文字や空データを判定するときに使うのが、empty?メソッドです。
Rubyで定義されているメソッドです。
blank?
present?メソッドとは逆に、有効な値でなかった場合にtrueを返すのが、blank?メソッドです。
つまり、「空白文字、無効値, 偽, 空データ」であればtrue、そうでなければfalseを返しますので、present?メソッドの使いどころの説明であげた「変数が有効な値ではない場合に、何らかの処理をしたい」ときに使えるメソッドです。
Rubyで定義されているメソッドです。つまり、present?メソッドの方が、blank?メソッドの逆(!blank?)を返すメソッドということになります。
presence
この6つの中で、唯一、真偽値以外を返すメソッドです。
判定方法はpresent?メソッドと同じく、「有効な値かどうか」ですが、有効な値だった場合は、その値を返します。(有効な値でなかった場合はnilが返ります)
例えば、present?メソッドを使用する場合を考えてみましょう。
present?メソッドでは、「有効な値であれば処理をする」ので、多くの場合、処理の中でその値を利用します。
例えば、aとbのどちらか有効な値である方をcへ代入する処理は、次のようなプログラムコードになるでしょう。(両方有効な場合は、aが優先)
if a.present? then
c = a
elsif b.present? then
c = b
else
c = nil
end
presenceメソッドを使えば、判定と同時に値を取得できますので、次のように書くことができるのです。
c = a.presence || b.presence
無効でなければnilが返されますので、結局はnil?メソッドなどを使わなければいけない場合もありますので、必ずpresenceメソッドの方が良いわけではありませんが、シンプルに書けるシーンであれば、使っていく方が良いでしょう。
なお、3項演算子を使えば、present?メソッドを使った分岐も1行で記載できます。c = a.present? ? a : b
https://web-camp.io/magazine/archives/12481
まとめ
変数が有効な値かどうかを判断するpresent?メソッドを紹介しました。
present?メソッドは、「有効な値」という複数条件をまとめて判定できるメソッドです。
この有効な値は、データベースの世界で有効な値ですので、データベースとやりとりするRailsアプリケーションでは、この判定はとても重要です。
データベースに不正な値が登録されないようにするだけではなく、不正な値が登録されていてもシステムを止めることなく動作させるために、present?メソッドを活用することができるでしょう。
もちろん、「有効な値」とは何かを理解しておかなければいけませんが、それを理解するということは、Railsの作法としてデータをどう表現するのかを知ることになります。
そういったノウハウ的な知識の積み重ねこそ、中級プログラマーにとって重要な部分なのです。
ぜひ、present?メソッドを通じて、Railsの作法の一端を感じてください。
なお、「ノウハウを得る」という意味では、現場の技術者の話を聞くのがもっとも確実で効率の良い方法です。もし、スクールなどで直接話す機会を持てるのであれば、ぜひ本物の技術者と話してみてください。世界が大きく広がることでしょう。
・present?メソッドは、有効な値であることを確認する
・有効な値とは「空白文字、無効値, 偽, 空データ」以外のこと
・present?メソッドは、「変数が「有効な値」であるときに何らかの処理をする」場合に使う
・配列でpresent?メソッドを使うと、要素が1つでもあれば(空データでなければ)trueが返ってくる
・defined?メソッドは、変数が定義されていればtrueを返す
・nil?メソッドは、変数がnilであればtrueを返す
・empty?メソッドは、変数が空データであればtrueを返す
・blank?メソッドは、変数が有効な値でなければtrueを返す
・presenceメソッドは、変数が有効な値であれば、その値を返す。そうでなければnilを返す