Rubyでの例外の発生と回復

Rubyで例外を発生・解除する方法

例外はRubyでのプログラミングの基本的な部分であり、開発者はエラーを優雅に処理し、堅牢で耐障害性の高いアプリケーションを保証することができます。Rubyの例外処理機構は直感的でありながら強力であり、開発者は何か問題が発生したときにエラーを発生させ、アプリケーションのクラッシュを防ぐためにエラーを救済することができます。この2000語のガイドでは、Rubyで例外を発生させ、それを救済する方法について、基本から高度なテクニック、ベストプラクティス、実例までを網羅しながら解説します。

Rubyの例外とは?

Rubyにおける例外とは、プログラム実行中のエラーや予期せぬ状況を表すオブジェクトである。ゼロで除算しようとした、存在しないファイルにアクセスした、ネットワークに障害が発生した、などのエラーが発生すると、Rubyは例外を発生させる。例外が処理されないと、エラーメッセージとともにプログラムが終了します。

Rubyの例外システムは 例外 クラスは例外階層のルートとなる。のようなサブクラスは 標準エラー(StandardError)、実行時エラー(RuntimeError)、引数エラー(ArgumentError、 そして メソッドエラー は特定のタイプのエラーを処理する。開発者は、アプリケーション固有のエラーを表すために、カスタム例外クラスを定義することもできる。

Rubyの例外処理は、2つの重要な動作を中心に展開される:

  • 育成:エラー発生時に例外を発生させる。
  • 救出:プログラムのクラッシュを防ぐための例外のキャッチと処理。

それでは、例外を効果的に発生させ、救済する方法について説明しよう。

Rubyで例外を発生させる

例外の発生は、エラーや予期せぬ状態が発生したことを知らせる処理である。Rubyでは レイズ メソッド(およびそのエイリアス 失敗)を使って例外を引き起こす。

について レイズ 方法

例外を発生させる最も簡単な方法は レイズ メソッドを引数なしで実行すると ランタイムエラー (のサブクラス)。 標準エラー):

ルビー
レイズ
# => RuntimeError: 処理されない例外

エラーメッセージを表示することもできます:

ルビー
raise "何かおかしい!"
# => RuntimeError:何か問題が発生しました!

特定の例外クラスを発生させるには、第1引数にそのクラス、第2引数にメッセージを渡す:

ルビー
raise ArgumentError, "無効な入力が提供されました"
# => ArgumentError:無効な入力が提供されました

カスタム例外クラス

より複雑なアプリケーションでは、特定のエラーを表すためにカスタム例外クラスを定義することができます。カスタム例外は 標準エラー またはそのサブクラスの1つを使って、Rubyのデフォルトのレスキュー動作との互換性を確保している。

例:

ルビー
class AuthenticationError  AuthenticationError:無効な認証情報

定義することによって 認証エラー認証関連のエラーは、一般的なエラーとは別に扱うことができる。

原因による例外の発生

Rubyでは例外に「原因」を付けることができ、デバッグに便利である。原因とは、現在の例外の原因となった元の例外のことである。例外に 例外 メソッドを使ってアクセスする:

ルビー
開始
  raise "オリジナルエラー"
rescue => e
  raise "新しいエラー" # 元のエラーが原因として保存される
終了

で原因を調べることができる。 e.原因:

ルビー
開始
  開始
    raise "オリジナルエラー"
  rescue => e
    raise "新しいエラー"
  end
rescue => e
  puts e.message # => 新しいエラー
  puts e.cause.message # => 元のエラー
end

例外の救出

例外の救済によって、エラーをキャッチして優雅に処理し、プログラムがクラッシュするのを防ぐことができる。Rubyでは 開始/救出 ブロックで例外を管理する。

について 始める/レスキュー ブロック

の基本構造 開始/救出 ブロックである:

ルビー
開始
  # 例外が発生するかもしれないコード
レスキュー
  例外を処理する
終了

例:

ルビー
開始
  結果 = 10 / 0
レスキュー
  puts "エラーが発生しました!"
終了
#出力:エラーが発生しました!

デフォルトでは、 レスキュー キャッチ 標準エラー とそのサブクラスがあります。例外クラスを指定しない場合は、次のようになります。 rescue StandardError.

特定の例外の処理

特定の例外を処理するには、例外クラスを レスキュー 条項

ルビー
開始
  結果 = 10 / 0
rescue ゼロ除算エラー
  puts "ゼロで割り切れない!"
rescue 引数エラー
  puts "無効な引数が指定されました!"
終了
# 出力:ゼロで除算できません!

さらに調べるために例外オブジェクトをキャプチャすることもできる:

ルビー
開始
  raise ArgumentError, "無効な入力"
rescue ArgumentError => e
  puts "エラー:#{e.message}"
end
#出力:エラー:無効な入力

使用する それ以外 そして 確保する

Rubyでは、例外処理のために2つの追加句が用意されている:

  • それ以外:例外が発生しなければ実行される。
  • 確保する:例外の発生に関係なく実行される。

例:

ルビー
開始
  puts "処理を実行中..."
  result = 10 / 2
rescue ゼロ除算エラー
  puts "ゼロで除算できません!"
else
  puts "操作に成功しました:#{result}"
確保
  puts "クリーンアップ..."
終了
# 出力:
# 操作の実行中...
# 操作に成功しました:5
# クリーンアップ中

例外が発生した場合

ルビー
開始
  puts "処理を実行中..."
  result = 10 / 0
rescue ゼロ除算エラー
  puts "ゼロで除算できません!"
else
  puts "操作に成功しました:#{result}"
確保
  puts "クリーンアップ..."
終了
# 出力:
# 演算中...
# ゼロによる除算ができません!
# クリーニング中...

について リトライ キーワード

について リトライ キーワードは 始める をブロックする。これは、失敗したネットワーク・リクエストを再試行するような場合に便利である。

例:

ルビー
試行回数 = 0
開始
  試行回数 += 1
  puts "試行回数#{試行回数}"
  raise "接続に失敗しました"
レスキュー
  リトライ if attempts < 3
  puts "#{attempts}回試行した時点でギブアップ"
終了
#の出力:
# 試行 1
# 試行 2
# 試行 3
# 3回試行してあきらめる

無限ループを避けるため、リトライは慎重に使用すること。

例外処理のベストプラクティス

  1. レスキュー特有の例外:むき出しは避ける レスキュー 節がある。 標準エラー サブクラスは、予期しないエラーを隠すことができる。期待する例外を正確に指定してください。
    ルビー
    # 悪い
    開始
      #コード
    レスキュー
      # 全てをキャッチ
    終了
    
    # グッド
    開始
      # コード
    rescue ArgumentError, TypeError
      # 特定のエラーを処理
    終了
  2. レスキューブロックは小さく:例外を発生させる可能性のあるコードだけをラップする。これは可読性を向上させ、無関係なエラーをキャッチするのを防ぐ。
  3. 意味のあるエラーメッセージの提供:例外を発生させるときは、デバッグを助けるために、明確で実用的なメッセージを含める。
  4. ドメイン・ロジックにカスタム例外を使用する:アプリケーション固有のエラーに対応するカスタム例外クラスを作成し、コードの表現力と保守性を高めます。
  5. フロー制御のために例外を使いすぎない:例外は例外的なケースのためのものであり、プログラムの流れを制御するためのものではない。想定されるシナリオには条件式を使う。
    ルビー
    # 悪い
    開始
    値 = hash[:key]
    レスキュー
    値 = nil
    終了
    
    # 良い
    値 = ハッシュ[:キー] || nil
  6. クリーンアップ・リソース 確保する:用途 確保する 例外が発生した場合でも、ファイル、データベース接続、その他のリソースをクローズします。

実例

ファイルハンドリング

ファイルを読むと、次のような例外が発生することがある。 Errno::ENOENT (ファイルが見つかりません)または Errno::EACCES (許可は拒否されました)。以下はその対処法である:

ルビー
開始
  File.open("nonexistent.txt", "r") do |file|.
    puts file.read
  終了
rescue Errno::ENOENT
  puts "ファイルが見つかりません!"
rescue Errno::EACCES
  puts "パーミッションが拒否されました!"
ensure
  puts "ファイル操作完了。"
終了
#出力:ファイルが見つかりません!
# ファイル操作完了。

APIコール

HTTPリクエストを行うと、ネットワークエラーや無効なレスポンスに遭遇することがあります。そのような場合は httpパーティー 宝石だ:

ルビー
httparty' を必要とする。

開始
  レスポンス = HTTParty.get('https://api.example.com/data')
rescue HTTParty::Error => e
  puts "APIリクエストに失敗しました: #{e.message}"
rescue SocketError
  puts "ネットワークエラーです:サーバーに接続できませんでした。
else
  puts "レスポンスを受信しました:#{レスポンス.ボディ}"
終了

クラス内でのカスタム例外処理

以下は、支払いを処理し、カスタム例外を使用するクラスの例です:

ルビー
class PaymentError < StandardError; end
class InsufficientFundsError < 支払いエラー; end
class InvalidCardError  card.balance
    card.balance -= amount
    puts "#{金額}の支払いが正常に処理されました"
  終了

  プライベート
  def valid_card?(card)
    card.number.length == 16
  終了
エンド

クラス Card
  attr_accessor :number, :balance
  def initialize(number, balance)
    番号 = 番号
    残高 = 残高
  終了
終了

カード = Card.new("1234567890123456", 50)
プロセッサー = PaymentProcessor.new

開始
  processor.process_payment(100, card)
rescue InsufficientFundsError => e
  puts "エラー:#{e.message}"
rescue InvalidCardError => e
  puts "エラー:#{e.message}"
終了
# 出力:エラー:資金不足

高度な例外処理

ネスト・レスキュー

入れ子にできる 開始/救出 ブロックを使って、さまざまなレベルの例外を処理することができる:

ルビー
開始
  開始
    raise "内部エラー"
  レスキュー
    puts "内部エラーを検出"
    raise "外側のエラー"
  end
rescue
  puts "外側のエラーを検出"
終了
#出力:
# キャッチされた内部エラー
# キャッチされた外側エラー

例外の階層

Rubyの例外階層を理解することは非常に重要です。主なクラスは以下の通りです:

  • 例外M:すべての例外のルートクラス。
  • 標準エラー:のデフォルト レスキュー ほとんどの組み込み例外はこれを継承している。
  • ランタイムエラー:のデフォルト レイズ クラスなし。
  • メソッドエラーなし、引数エラー、タイプエラーなど:特定のエラータイプ。

を含む)すべての例外を捕捉する。標準エラー のようなものです。 システム終了) を使用する。 レスキュー例外:

ルビー
始める
  終了
rescue 例外
  puts "終了をキャッチ"
終了
#出力:キャッチされた終了

使用する レスキューフロム in Rails

Ruby on Railsでは レスキューフロム 例外をグローバルに処理するために、コントローラの

ルビー
クラス ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, with: :not_found

  プライベート

  def not_found
    ファイルをレンダリングする:'public/404.html', status: :not_found
  終了
終了

このアプローチは、特定のコントローラの例外処理を一元化する。

避けるべき一般的な落とし穴

  1. すべての例外をやみくもにキャッチする:使用中 レスキュー 例外クラスを指定しないと、バグを隠すことができる。
  2. 酷使 リトライ:無限にリトライを繰り返すと、無限ループに陥ったり、根本的な問題を覆い隠してしまう可能性がある。
  3. 例外の詳細を無視する:常に例外オブジェクト (e.message, e.backtrace)をデバッグする。
  4. 非標準エラーの発生:を継承しない例外の発生を避ける。 標準エラーデフォルトでは捕まらないからだ。 レスキュー 節がある。
  5. 資源の後始末をしない:使い忘れ 確保する はファイルや接続を開いたままにすることができる。

結論

Rubyで例外を発生させ、それを救済することは、エラーを処理し、堅牢なアプリケーションを構築するための強力な方法です。このセクションでは レールカーマをリードしている。 Ruby on Rails開発会社私たちは、これらのテクニックを活用して、信頼性と保守性の高いソリューションを構築しています。そのために レイズ エラーを知らせる、 レスキュー のような道具がある。 再試行する。、 そして 確保する開発者はエラーを効果的に管理することができます。カスタム例外クラスと特定のレスキュー条項が、コードに明快さと正確さを加えます。特定の例外をレスキューする、レスキュー・ブロックを小さく保つ、意味のあるエラー・メッセージを使用するといったベスト・プラクティスに従うことで、保守性と信頼性の高いコードを実現できます。

ファイル操作、APIコール、ドメイン固有のロジックのいずれを処理する場合でも、Rubyの例外処理システムはエラーに潔く対処する柔軟性を提供します。これらのテクニックをマスターし、よくある落とし穴を回避することで、RailsCarma は企業が自信を持ってエラーを処理する回復力のある Ruby アプリケーションを構築できるよう支援します。

関連記事

投稿者について

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


jaJapanese