Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Railsコントローラのアクションがrenderで終わるとは限らない(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Railsコントローラのアクションがrenderで終わるとは限らない(翻訳)

今回はRailsのちょっとした小技をご紹介します。こんなライブラリを使っているところを想像してみてください。そのライブラリはコントローラー内でいくつかのロジックを実行し、必要な指定が不足している場合は、それに応じていくつかのテンプレートをレンダリングします。このライブラリは古くから存在する、JSON APIを使わずにHTMLテンプレートのみをレンダリングしていた時代に作成されたものだとしましょう。さて、APIコントローラに同様のロジックを追加する必要が生じました。JSONレスポンスを処理するようにライブラリを変更すべきだと思うかもしれませんが、解決方法は他にもあるのです。

コントローラのrenderメソッドを実行しても、アクションの処理を終了して制御フローを返すわけではないことを思い出しましょう。したがって、renderを呼び出した後でも、レスポンスの変更などの操作は引き続き可能です。ただし、1つのアクション内でrenderを複数回呼び出すことはできません(DoubleRenderErrorという例外が発生します)。

つまり、そのライブラリにまったく触らずにアクションを拡張できるということです。そのライブラリが、例外発生時にテンプレートをレンダリングするメソッドを持つモジュールを公開しているとしましょう(これは単なる例なので、ライブラリの出来はここでは問題にしません)。

module ActivationCheck

  def check_active(id)
    ActivationChecker.new.call(id) # 指定のidを持つプロジェクトがアクティブならtrue、それ以外ならエラーをraise
  rescue ActivationCheck::Error => exc
    render("activation_check/error", message: exc.message)
    false
  end
end

そしてAPIコントローラが以下のようになっているとしましょう。

class ProjectsController
  include ActivationCheck

  def show
    project = Project.find(params[:id])
    if check_active(project.id)
      render json: project
    end
  end
end

このライブラリをコントローラで使うときの問題は、check_activeメソッドがfalseを返したときにレスポンスでステータス200 OKのHTMLテンプレートもレンダリングされてしまうことです。JSONテンプレートを作成して、ライブラリが提供するデフォルトのHTMLテンプレートを上書きすることは可能ですが、それでもステータス200 OKが返ってしまいます(レスポンスが成功していないのに成功したというステータスコードを返すべきではありません)。これに対処するために、フローの後半でレスポンスのステータスを直接変更してみましょう。

class ProjectsController
  include ActivationCheck

  def show
    project = Project.find(params[:id])
    if check_active(project.id)
      render json: project
    else # この分岐で既にActivationCheckがテンプレートをレンダリングしている
      response.status = :bad_request
    end
  end
end

後は、JSONテンプレートを作成してデフォルトのテンプレートを上書きすれば(例: app/views/activation_check/error.json.erb)、元のライブラリに手を加えずに、コントローラで適切なステータスコードのJSONレスポンスを返せるようになります。

お知らせ

ARKADEMY.DEVに参加してArkencyのトップクラス教育プログラムコースにアクセスしましょう!「Railsアーキテクトマスタークラス」「アンチ"IF"コース」「忙しいプログラマーのためのブログ執筆コース」「Async Remoteコース」「TDD動画クラス」「ドメイン駆動Rails動画コース」以外にもさまざまなコースが新設中です。

関連記事

ソフトウェアパターンを闇雲に適用しないこと(翻訳)


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。