はじめに
プログラミングにおいてエラーは無いにこしたことはありませんが、開発者も人間なのでミスすることもあるし、ネットワークのエラーで開発者がどうしようもなくエラーが発生することもあります。
エラーと言っても色々な種類があります。「こういうエラーが起きた場合はこうする」という処理を書いておくべき場面は多々ありますが、そんな時に使えるrescueとrescue_fromについての基礎的な使い方です。
rescue
rescueを使うと、エラーが発生した場合それを拾って次に行う処理を書くことができます。
以下はrescueがない場合とある場合の違いです。
Userクラスはnameカラムしか持たないようにして、あるuserを作ります。
> user = User.new('山田')
=> #<User:0x00007ff0fa896758 @name="山田">
> user.name
=> "山田"
Userクラスにputs_infoメソッドを作り、実行します。
class UsersController < ActionController::Base
  def puts_info
    "名前は" + name
  end
end
> user.puts_info
=> 名前は山田
puts_infoメソッドに存在しないageメソッドを加え、実行します。
class UsersController < ActionController::Base
  def puts_info
    "名前は" + name
    "年齢は" + age
  end
end
> user.name
=> "山田"
> user.puts_info
=> NameError (undefined local variable or method `age' for #<User:0x00007fdeb98f3ed8 @name="山田">)
NameErrorになりました。
rescueを使って、エラーの場合の処理を書いてあげます。
class UsersController < ActionController::Base
  def puts_info
    "名前は" + name
    "年齢は" + age
  rescue => e
    "エラーです"
  end
end
> user.puts_info
=> "エラーです"
rescue NameError => e
のように例外クラスを指定して拾うこともできます。
詳しく知りたい方は以下の記事がおすすめです。
rescue_from
rescue_fromは、特定の種類または複数の種類の例外を1つのコントローラ全体およびそのサブクラスで扱えるようになります。
例:404エラー(そんなページありませんよ)の場合にrecord_not_foundというメソッドを実行させる。
class UsersController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
  private
    def record_not_found
      render plain: "404 Not Found", status: 404
    end
end
例:adminユーザー以外はeditページに入れない、という仕様を実装する
1, Clientコントローラーで、editアクション実行前にbefore_actionで権限チェックの処理を行います。
check_authorizationメソッド内でcurrent_user.admin?を行い、管理者ではない場合は、raiseを使ってUser::NotAuthorizedという例外を発生させます。
class ClientsController < ApplicationController
  before_action :check_authorization
  def edit
    @client = Client.find(params[:id])
  end
  private
    def check_authorization
      raise User::NotAuthorized unless current_user.admin?
    end
end
2, ApplicationControllerに、User::NotAuthorizedというエラーの場合にuser_not_authorizedメソッドを実行させる処理を書きます。
class ApplicationController < ActionController::Base
  rescue_from User::NotAuthorized, with: :user_not_authorized
  private
    def user_not_authorized
      flash[:error] = "あなたはこのページにアクセスする権限がありません。"
      redirect_back(fallback_location: root_path)
    end
end
こうすることで、権限エラーの場合には「権限がありません」という表示をしてあげることができますし
、editアクション内では権限に関して心配する必要がなくなります。
edit以外にも管理者権限を必要とするメソッドがある場合には、before_actionを使ってcheck_authorizationを実行してあげればいいですね。
参考