0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】エラーハンドリングで e.message || が空文字を拾ってしまう問題

Posted at

はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。

Rails で rescue_from を使ってエラーハンドリングするときに、つい

e.message || I18n.t("application.errors.not_found")

と書いてしまうことはありませんか?
一見これで「e.message がなければ翻訳メッセージを出す」ように見えますが、実は思わぬ落とし穴があります。


問題となるケース

例えば以下のようなコード:

rescue_from ActiveRecord::RecordNotFound do |e|
  render_error!(
    code: "NOT_FOUND",
    field: "base",
    message: e.message || I18n.t("application.errors.not_found"),
    status: :not_found
  )
end

上記はオリジナルメソッドですが、要は情報を渡してjsonレスポンスを返すだけのものです。

このとき、もし e.message空文字 "" の場合、どうなるでしょうか?

実際には…

"" || I18n.t("application.errors.not_found")
# => ""

となり、空文字がそのまま返ってしまうのです。
つまりエラーメッセージが空っぽのレスポンスになってしまいます。


なぜ起きるのか?

Ruby の || は「nil または false なら右側を評価」する仕組みです。
空文字 "" は truthy(真)なので || の左側として成立してしまい、右側が評価されません。


解決方法:presence を使う

Rails が提供する Object#presence を使うと、この問題を簡単に回避できます。

e.message.presence || I18n.t("application.errors.not_found")

presence は以下のように動きます:

  • 値が nil や空("", [], {} など) → nil を返す
  • それ以外ならそのまま返す

つまり、e.message が空文字だった場合でも nil に変換されるので、期待通りフォールバックできます。


まとめ

  • e.message || ... だけだと、空文字がそのまま返ってしまう
  • Ruby の || 判定は「nil または false」だけ
  • Rails の presence を組み合わせることで、空文字でもちゃんとフォールバック可能

エラーメッセージを返すときは e.message.presence || I18n.t(...) を意識しておくと安心です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?