今回は、nil判定の方法やnilの概念、そしてnilが原因のエラーの回避方法についてご紹介させていただきます。
開発を進める中でnilは厄介なオブジェクトですが、今回ご紹介する内容を頭に入れておけば怖いものはありません。
そんな悩みをお持ちの方々に向けて分かりやすく簡潔にご説明していきますので、ぜひ最後まで読んでみてください。
なお、Rubyの魅力や特徴については以下の記事で詳しく解説していますので、こちらもぜひご覧くださいね。
みなさんこんにちは! 今回の記事は、 悩みを抱えた人 ・Rubyってどんなプログラミング言語なの?・Rubyを勉強すると将来役に立つかな?・Rubyのおすすめの学習方法が知りたい! というお悩みを解決する記事にな[…]
フリーランス案件を探すならこのエージェント!
転職を考えているならこのエージェント!
nilとは
まず初めに、nil
とは何かについてご説明させていただきますね。
nil
とは、簡単に言うと、「存在しない」という意味です。
この説明を聞いた段階では、「なるほど、""
とか[]
とか、0
なんかがnil
ということなんだな」と思われる方も多いかと思いますが、Ruby(というよりもプログラミング言語)はこれらを「存在している」ものと解釈します。
実際に確かめてみると以下のような結果が得られます。
(※「nil?」メソッドは、nilかどうかを確認するメソッドです。詳しくは次章でご説明しますね。)
irb(main):001:0> "".nil?
=> false
irb(main):002:0> [].nil?
=> false
irb(main):003:0> 0.nil?
=> false
このように、「中身は空だがオブジェクトとしては存在している」ものとして解釈されます。
実際の開発では、想像以上にこのnil
が出てきてしまい、思わぬエラーを発生させてしまいますので、このnil
をどのように回避していくかが非常に重要になってくるのです。
それでは早速、オブジェクトがnil
かどうかを判定する方法を見てきましょう。
Rubyでnil判定をする方法まとめ
Rubyを使ってnil判定をする方法としては以下の4つが挙げられます。
- 1. nil?
- 2. empty?
- 3. blank?
- 4. present?
それぞれ順を追ってご説明させていただきますね。
Rubyでnil判定をする方法その1 nil?メソッド
まずご紹介するのは、「nil?」メソッドです。
先ほど少しご紹介しましたが、nil?メソッドを使用すると、そのオブジェクトがnil
かどうかを判定することができ、戻り値はBoolean値(true/false)になります。
irb(main):001:0> "".nil?
=> false
irb(main):002:0> [].nil?
=> false
irb(main):003:0> test = nil
irb(main):004:0> test.nil?
=> true
Rubyでnil判定をする方法その2 empty?メソッド
続いてご紹介するのは、「empty?」メソッドです。
empty?メソッドは厳密に言うとnil
を判定するものではなく、オブジェクトが空かどうかを確認するためのメソッドになります。
irb(main):001:0> "".empty?
=> true
irb(main):002:0> [].empty?
=> true
irb(main):003:0> "Ruby".empty?
=> false
irb(main):004:0> ["Ruby", "Rails"].empty?
=> false
このように、空の文字列や配列に対してempty?メソッドを使用するとtrueが返ってきているのがお分かりいただけるかと思います。
他方で、「中身が空かどうかを確認する」ということは、少なくとも中身を入れるための「入れ物」が必要ということになり、nilやBoolean値、或いは数字に対してempty?メソッドを呼び出すとNoMethodErrorが発生してしまいますのでご注意くださいね。
irb(main):001:0> nil.empty?
=> NoMethodError (undefined method `empty?' for nil:NilClass)
irb(main):002:0> true.empty?
=> NoMethodError (undefined method `empty?' for true:TrueClass)
irb(main):003:0> 0.empty?
=> NoMethodError (undefined method `empty?' for 0:Integer)
Rubyでnil判定をする方法その3 blank?メソッド
続いてご紹介するのは、「blank?」メソッドです。
blank?メソッドですが、Railsで拡張されたメソッドのため、Ruby単体では使用することはできません(NoMethodError
が発生します)。
ただし、Rubyを用いて開発する際には多くの場合Railsを使いますので、こちらのメソッドもぜひ覚えておきましょう。
blank?メソッドは、簡単に言うと、これまでのnil?メソッドとempty?メソッドの機能を組み合わせたメソッドです。
つまり、nil
か中身が空のオブジェクトの場合にtrueを返してくれます。
[1] pry(main)> nil.blank?
=> true
[2] pry(main)> [].blank?
=> true
[3] pry(main)> "".blank?
=> true
[4] pry(main)> false.blank?
=> true
[5] pry(main)> 0.blank?
=> false
empty?メソッドだとnilチェックができなかった(NoMethodError
が発生していた)ので、とても便利になりましたよね。
なお、あまり出くわす機会はないとは思いますが、false
に対してblank?メソッドを使用した場合にもtrue
が返ってきますので、ご注意くださいね。
Rubyでnil判定をする方法その4 present?メソッド
最後にご紹介するのは、「present?」メソッドです。
こちらもblank?メソッドと同様にRailsにて拡張されたメソッドです。
その機能としては、blank?メソッドの反対、つまりnil
か中身が空のオブジェクトの場合にはfalseを返します。
[1] pry(main)> nil.present?
=> false
[2] pry(main)> [].present?
=> false
[3] pry(main)> "".present?
=> false
[4] pry(main)> false.present?
=> false
[5] pry(main)> 0.present?
=> true
nil判定をした際の結果まとめ
さて、ここまでRuby/Railsを使ってnil判定する方法を見てきましたが、「結局のところどれを使ったらいいの?」という疑問をお持ちの方も多いかと思います。
そんな方々に向けて、私の方で様々なケースを試し、以下の表の通りまとめてみましたので、ど忘れしたり迷ってしまった際にはぜひこちらをご参照ください。
(※左端の列には「対象となるオブジェクト(レシーバ)」を記載し、4つのメソッドの戻り値をそれぞれ記載しています)
nil? | empty? | blank? | present? | |
---|---|---|---|---|
nil | true | NoMethodError | true | false |
数字(0も含む) | false | NoMethodError | false | true |
“” | false | true | true | false |
” “(半角/全角スペース) | false | false | true | false |
{} | false | true | true | false |
[] | false | true | true | false |
true | false | NoMethodError | false | true |
false | false | NoMethodError | true | false |
開発の中でnilを回避する方法
さて、続いては、実際に開発する中でいかにしてnil
によるエラーを防いでいけば良いかということをご紹介していきます。
ではまず、nil
によってどのようなエラーが発生するかを見ておきましょう。
nil
が原因で発生するエラーはズバリNoMethodError
です。
irb(main):001:0> nil.empty?
=> NoMethodError (undefined method `empty?' for nil:NilClass)
上記の通り、nil
はNilClass
のインスタンスであり、そのNilClass
にメソッドが登録されていないためにこのエラーが発生してしまうのです。
「え、nilが使えるメソッドってそもそもあるの?」と思われた方、実は結構な数のメソッドが存在しているのです。
気になる方は、nil.methods
と調べてみてください。まあまあびっくりされると思います。
さて、少し話が脱線しましたが、nil
によるエラー(NoMethodError
)を防ぐためには主に以下の2つの手段があるかと思います。
- 1. そもそもnilを作らない
- 2. nilに対してメソッドを呼び出してもエラーを発生させないようにする
まずは、最初の「そもそもnilを作らない」という方法をご紹介します。
(※こうした「nilを回避する」方法は「nilガード」とも呼ばれます)
Rubyでnilを回避する方法その1 ||(パイプ演算子)
と=
を使用する
そもそも「nilを作らない」ためには、||(パイプ演算子)
と=
を使用します。
# オブジェクトがnilの場合
irb(main):001:0> language = nil
irb(main):002:0> language ||= "Ruby"
irb(main):003:0> language
=> "Ruby"
# オブジェクトがnilではない場合
irb(main):001:0> language = "Rails"
irb(main):002:0> language ||= "Ruby"
irb(main):003:0> language
=> "Rails"
上記のように、||(パイプ演算子)
と=
を使用することで、オブジェクトがnilの場合にのみ値を代入することができます。
上記に構文は実際の開発の中でも頻繁に使用しますので、この機会にぜひ覚えておいてくださいね。
Rubyでnilを回避する方法その2 &.(ぼっち演算子)
ここからは、「nilに対してメソッドを呼び出してもエラーを発生させないようにする」方法を見ていきます。
まず最初は、「&.(ぼっち演算子)」になります。この「ぼっち」ですが、見た目が一人ぼっちの人のように見えることからこのように呼ばれています。
この&.(ぼっち演算子)を使用すると、レシーバがnilの場合であってもNoMethodError
が発生しないようになります。
# &.(ぼっち演算子)を使用しない場合
irb(main):001:0> nil.empty?
=> NoMethodError (undefined method `empty?' for nil:NilClass)
# &.(ぼっち演算子)を使用した場合
irb(main):001:0> nil&.empty?
=> nil
ただし、レシーバがnilではなく且つそのレシーバが持っていないメソッドを呼び出してしまうとNoMethodError
が発生してしまいます。
irb(main):001:0> nil&.empty?
=> nil
irb(main):002:0> 100&.empty?
=> NoMethodError (undefined method `empty?' for 100:Integer)
irb(main):003:0> "Ruby"&.empty?
=> false
上記を踏まえると、レシーバのクラスが確定していない場合(「文字列」も「数字」も入る可能性のある場合 など)には、&.(ぼっち演算子)を使用してもまだNoMethodError
が発生する可能性が残ってしまうということになります。
Rubyでnilを回避する方法その3 tryメソッド
このような状況を打破するために登場したのが、「try」メソッドです。
この「try」メソッドは、&.(ぼっち演算子)とは異なり、「レシーバが持っていないメソッド」を呼び出してもNoMethodError
が発生しません(nil
を返します)。
[1] pry(main)> nil.try(:empty?)
=> nil
[2] pry(main)> 100.try(:empty?)
=> nil
[3] pry(main)> "Ruby".try(:empty?)
=> false
ただし、こちらも上記でご説明した「blank?」メソッドや「present?」メソッドと同様にRailsで拡張されたメソッドですので、Ruby単体の環境では動きませんのでご注意くださいね。
でも、何でもかんでもtryするのはやめておきましょう
ここまでを踏まえると、「とりあえずtryを使っておけば安全だな」と思われる方もいらっしゃると思いますが、実際の開発ではあまり多用しないようにしましょう。
というのも、「オブジェクトがnilの場合」や「メソッドが存在しない場合」にエラーが発生しないということにより、思わぬバグに気づくことができない(バグを握り潰してしまう)のです。
特に、後者の「メソッドが存在しない場合」については、そもそも期待していたものとは異なるクラスのオブジェクトが返ってきているということですので、この場合には実装自体を見直した方がよいです。
もちろん、これらの要素を把握した上でなおtry
を使用するということであれば問題はありませんが、「とにかくエラーをなくそう」としてtry
を連発してしまうのだけは避けましょうね。
お仕事の途中ですが、少し一休みして、転職や独立について考えてみませんか🙌?
現役エンジニアが選ぶおすすめの転職エージェント11選【成功談・失敗談もあります】
レバテックフリーランスの評判ってどう?【現役エンジニアが徹底解説します】
MidWorks(ミッドワークス)の評判ってどう?【現役エンジニアが徹底解説します】
日々の業務に追われて自分を見失わないよう、
定期的にキャリアを振り返るようにしておきましょう🤲
最後に
さて、ここまで、nil判定の方法やnilの概念、そしてnilの回避方法についてご紹介してきましたがいかがでしたか?
nil
は絶対悪のようなイメージを持ってらした方もいらっしゃると思いますが、決してそんなことはありません。
実際の開発を進める中で必ずと言ってよいほどnil
は現れてきますので、「nil
を減らす」ことも大事ですが、「出てきたnil
にどのように対応するか」ということも重要になってきます。
今回ご紹介したメソッドなどを活用し、なるべくエラーの発生しない綺麗なコードを書いていってくださいね。
このブログを通じて少しでも「傍(はた)を楽(らく)にする」ことができていれば嬉しく思います。
最後まで読んで頂きありがとうございました。