🐟

[Rails]respond_toメソッドでリクエストフォーマットによってレンダリングを変える

2021/10/19に公開約2,300字

コンテンツのフォーマットによって表示を出し分け

RailsではHTMLだけでなく、JSONやXMLなどその他のフォーマットで表示させることもできます。

同じアクション内部でビューの出し分けをするための方法を見ていきます。

respond_toメソッド

リクエストの形式(HTMLやJSONなど)によって処理・レンダリングを変えるにはrespond_toメソッドを使います。

app/controllers/books_controller.rb

class BooksController < ApplicationController
  def show

    @book = Book.find(params[:id])
    # リクエスト時のフォーマットによって対応するレスポンスをコントローラで制御している
    respond_to do |format|
      # htmlでリクエストされたときshow.html.erbをレンダリング。ブロックは省略可
      format.html { render :show, format: :html }
      
      # jsonでリクエストされたとき(render :show, format: :json)と同義
      # ブロックで渡さなくても、レンダリングできるが明示的にすることで柔軟に変更できる
      format.json { render json: @book }
    end

  end
end

ポイント

  • 処理をrespond_to do |format| 〜 endのブロックで囲います。
  • format.html { render :show, format: :html }でHTMLテンプレートでshowアクションのテンプレートを参照します。(show.html.erb)
  • format.json { render json: @book }で同じくshow.json.erbのように規約に合致するテンプレートを参照します。
  • 例えば「/books/1.json」というパスでアクセスされた場合は、jsonフォーマットのレスポンスを要求していると解釈できる。
  • つまり、リクエスト時のフォーマットによって対応するレスポンスをコントローラで制御しています。

render処理ではなくリダイレクトしたい場合

また、renderによる描画ではなく、リダイレクト処理をしたい場合もあると思います。

そんなときは、例えば下記のように処理を書くことができます。

class BooksController < ApplicationController

  def show
    @book = Book.find(params[:id])
    # リクエスト時のフォーマットによって対応するレスポンスをコントローラで制御している
    respond_to do |format|
      # htmlでリクエストされたとき(render :show, format :html)と同義
      format.html { redirect_to profile_path }

      # jsonでリクエストされたとき(render :show, format :json)と同義
      # ブロックで渡さなくても、レンダリングできるが明示的にすることで柔軟に変更できる
      format.json { render json: @book }
    end
end

ステータスコードを返す

headメソッドでステータスコードのシンボルを渡せます。

def destroy
  @book.destroy
  respond_to do |format|
    format.html { redirect_to "/" }
    # :no_contentというシンボルを指定すると204のステータスコードを返す(redirection)
    format.json { head :no_content }
  end
end
コード番号 シンボル
200 :ok
201 :created
202 :accepted
204 :no_content
304 :not_modified
400 :bad_request
401 :unauthorized
403 :forbidden
404 :not_found
409 :conflict
422 :unprocessable_entity

Discussion

ログインするとコメントできます