【Ruby】nilの扱い方でハマらないために

Ruby

こんにちは、かつコーチです。

Rubyを書いていると、必ずと言っていいほど出会うのがnil関連のエラーです。

私も実務でAPIのレスポンスを扱っていたとき、想定外のnilに何度も足元をすくわれました。

この記事では、nilとは何かという基本から、nil?メソッドやぼっち演算子を使った安全な書き方までを解説します。

基本の書き方・nilの正しい扱い方

nilとは「何もない」ことを表す値

nilとは、Rubyにおいて「値が存在しない」ことを表す特別なオブジェクトです。

他の言語のnullNoneに近い存在ですが、Rubyではnil自体もNilClassというクラスのオブジェクトです。

p nil.class
# => NilClass

変数の初期化前や、ハッシュに存在しないキーを参照したときなどに、nilが返ってきます。

user = { name: "Sato" }
p user[:age]
# => nil

nil?メソッドで存在チェックをする

nil?メソッドとは、そのオブジェクトがnilかどうかを真偽値で返すメソッドです。

value = nil
p value.nil?
# => true

value = "Ruby"
p value.nil?
# => false

if文と組み合わせれば、nilだった場合の分岐処理を安全に書けます。

def greet(name)
  if name.nil?
    puts "名前が指定されていません"
  else
    puts "Hello, #{name}"
  end
end

greet(nil)
# => 名前が指定されていません

ぼっち演算子(&.)でnilガードする

ぼっち演算子(&.)とは、レシーバーがnilのときにメソッド呼び出しをスキップしてnilを返す演算子です。

見た目が体育座りをしている人に似ていることから、この呼び名がついています。

user = nil
p user&.name
# => nil

通常の.で呼び出すとエラーになる場面でも、&.を使えばエラーにならずnilが返ります。

users = [{ name: "Sato" }, nil, { name: "Suzuki" }]

users.each do |user|
  puts user&.[](:name) || "不明なユーザー"
end
# => Sato
# => 不明なユーザー
# => Suzuki

よくあるつまずきポイント・エラー対処

NoMethodError for nil:NilClassへの対処

NoMethodError for nil:NilClassとは、nilに対して存在しないメソッドを呼び出したときに出るエラーです。

❌ Before

def fetch_user_name(users, id)
  user = users.find { |u| u[:id] == id }
  user[:name].upcase
end

users = [{ id: 1, name: "Sato" }]
puts fetch_user_name(users, 2)
undefined method '[]' for nil (NoMethodError)

実際に私がAPI連携の実装で経験したのが、まさにこのパターンです。

findで条件に合うデータが見つからないとnilが返ってくるのに、その後すぐに[:name]でアクセスしてしまい、本番環境でエラーが発生しました。

✅ After

def fetch_user_name(users, id)
  user = users.find { |u| u[:id] == id }
  user&.[](:name)&.upcase || "ユーザーが見つかりません"
end

users = [{ id: 1, name: "Sato" }]
puts fetch_user_name(users, 2)
# => ユーザーが見つかりません

finddetectのように「見つからなければnilを返す」メソッドの後には、必ずnilチェックを入れる習慣をつけましょう。

配列の空チェックとnilチェックの混同

配列が「空である」ことと「nilである」ことを混同してしまうのも、よくあるつまずきです。

❌ Before

def show_items(items)
  if items.nil?
    puts "アイテムがありません"
  end
  items.each { |item| puts item }
end

show_items([])
(何も表示されないが、なぜ表示されないのか分かりにくい)

itemsnilではなく空配列[]だった場合、nil?のチェックをすり抜けてしまい、eachが0回実行されて終わります。

エラーにはなりませんが、意図した「アイテムがありません」の表示がされず、原因調査に時間がかかりました。

✅ After

def show_items(items)
  if items.nil? || items.empty?
    puts "アイテムがありません"
    return
  end
  items.each { |item| puts item }
end

show_items([])
# => アイテムがありません

nilか空かの両方を考慮したいときは、nil?empty?をセットで使うか、Array()nilを空配列に変換してから処理すると安全です。

まとめ

この記事のポイント

  • nilはRubyで「値が存在しない」ことを表すNilClassのオブジェクトである
  • nil?メソッドを使えば、nilかどうかを安全に判定できる
  • ぼっち演算子(&.)を使うと、nilに対するメソッド呼び出しでもエラーにならない
  • findなど「見つからなければnilを返す」メソッドの後は、必ずnilチェックを入れる
  • nilと空配列は別物なので、両方を考慮した条件分岐が必要になる場合がある

次に読むべき記事

nilの扱い方に慣れたら、次はプロジェクトの土台となるライブラリ管理を学びましょう。

「Gemfileとbundlerの基本:パッケージ管理を理解する」で、gemの仕組みとbundle installの挙動を解説しています。

タグ: #Ruby #初心者向け #エラー解決

タイトルとURLをコピーしました