すでにメンバーの場合は

無料会員登録

GitHubアカウントで登録 Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

登録がまだの方はこちらから

Pikawakaにログイン

GitHubアカウントでログイン Pikawakaが許可なくTwitterやFacebookに投稿することはありません。

Rails

【Rails】respond_toメソッドの使い方をマスターしてリクエストのフォーマットで処理を分けよう!

ぴっかちゃん
ぴっかちゃん

respond_toメソッドとは、リクエストで指定されたフォーマットによって処理を分ける事が出来るメソッドです。

respond_toメソッドは、以下のように記述する事でリクエストされるフォーマット(HTML形式、JSON形式など)によって処理を分ける事が出来ます。

app/controllers/users_controller.rb | リクエストされるフォーマットによって処理を分ける
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class UsersController < ApplicationController
  def index
    @users = [
      { name: "田中", age: 22 },
      { name: "伊藤", age: 19 }
    ]

    respond_to do |format|
      # リクエストされるフォーマットがHTML形式の場合
      format.html 

      # リクエストされるフォーマットがJSON形式の場合
      format.json { render json: @users } 
      # @usersをjson形式のデータへ変換して返す
    end
  end
end

例えば「localhost:3000/users.json」にアクセスすると、リクエストされるフォーマットはJSON形式になるので、上記のformat.jsonに記述した処理が実行されて、以下の動画のようにJSON形式に変換されたユーザーのデータが表示されます。

respond_toメソッドのJSON形式の処理の全体の流れ

そして、特にフォーマットが指定されてない「localhost:3000/users」にアクセスした場合は、以下の動画のようにリクエストされるフォーマットはHTML形式になるのでformat.htmlが実行されます。

respond_toメソッドのHTML形式の処理の全体の流れ

format.htmlの後に処理がない場合は、以下のindexアクションに対応するViewファイルが呼び出されます。

app/views/users/index.html.erb | HTML形式でリクエストされた場合に呼び出されるViewファイル
1
2
3
4
5
<h1>Users</h1>

<% @users.each do |user| %>
  <p><%= user[:name] %>さん【<%= user[:age] %>才】</p>
<% end %>

このように、respond_toメソッドを使えばリクエストされるフォーマットごとに処理を分ける事が出来ます。

respond_toメソッドの使い方

respond_toメソッドが「何をしているか良く分からない」という方は、そもそも「リクエストされるフォーマット」が何なのか理解出来ていないことが原因の1つとしてあります。

その為、この章ではrespond_toメソッドの基本構文や使い方だけではなく、リクエストされるフォーマットにも焦点を当てて処理の流れを理解する事が出来るように解説します。

基本構文

まずは、respond_toメソッドの基本構文を確認していきましょう。

以下のように、respond_toメソッドのブロック引数formatを使ってformat.形式と記述すると、指定した形式ごとに処理を分ける事が出来ます。

respond_toメソッドの基本的な書き方
1
2
3
respond_to do |format|
  format.形式 { 処理 }
end

例えば、indexアクション内で「HTML形式、JSON形式、JS形式」の各フォーマットのリクエストによって処理を分けたい場合は、以下のように記述します。

各フォーマットごとの指定方法
1
2
3
4
5
6
7
8
9
class UsersController < ApplicationController
  def index
    respond_to do |format|
      format.html # リクエストされるフォーマットがHTML形式の場合
      format.json { 処理 } # リクエストされるフォーマットがJSON形式の場合
      format.js { 処理 } # リクエストされるフォーマットがJS形式の場合
    end
  end
end

このようにrespond_toメソッドを使うと、リクエストのフォーマットによって処理を分けて記述できる事が分かりますが、「リクエストのフォーマット」とは具体的にどういうものなのでしょうか?

リクエストのフォーマットとは?

リクエストのフォーマットは、「localhost:3000/users.json」の.jsonのように拡張子をつける事で指定する事が出来ます。この場合リクエストされるフォーマットはJSON形式になります。

また「localhost:3000/users」のように、特にフォーマットが指定されていない場合はデフォルトのHTML形式でリクエストが送信されます。

それでは、実際にリクエストされるフォーマットをbinding.pryで調べてみましょう。

app/controllers/users_controller.rb | format.形式の後にbinding.pryを使ってフォーマットを確認する
1
2
3
4
5
6
7
def index
  respond_to do |format|
    format.html { binding.pry }
    format.json { binding.pry }
    format.js { binding.pry }
  end
end

上記のように各形式の処理にbinding.pryを記述して、その形式のリクエストがきたら処理が止まるようにします。

HTML形式の場合

まずは、HTML形式のリクエストが送信された場合を確認します。

以下の動画のように「localhost:3000/users」にアクセスすると、Pryが起動しformat.htmlの箇所で処理が止まります。

HTML形式の場合のリクエストのフォーマット

そして、リクエストされる形式を調べてくれる「request.format」を実行すると、「localhost:3000/users」で送信されたリクエストのフォーマットがHTML形式だという事が分かります。

このように、送信されるリクエストのフォーマットがHTML形式なので、format.htmlに記述する処理(binding.pry)が実行されます。

最後にターミナルでexitを実行すると、Pryが終了して対応するindex.html.erbが呼び出されます。

JSON形式の場合

次にJSON形式のリクエストが送信された場合を確認します。

以下の動画のように「localhost:3000/users.json」にアクセスすると、Pryが起動しformat.jsonの箇所で処理が止まります。

JSON形式の場合のリクエストのフォーマット

先ほどのHTML形式の場合のように、Pryでrequest.formatを実行すると「localhost:3000/users.json」で送信されたリクエストのフォーマットがJSON形式だと分かります。

このように、送信されるリクエストのフォーマットがHTML形式なので、format.jsonに記述する処理(binding.pry)が実行されます。

そして、ターミナルでexitを実行するとPryが終了して、対応するindex.json.erbが呼び出されます。

JS形式の場合

最後に、JS形式のリクエストが送信された場合を確認します。
JSの場合は「localhost:3000/users.js」にアクセスしますが、このままだとRailsのCSRF対策に引っ掛かりエラーが発生するので、以下のコードを追加します。

app/controllers/users_controller.rb | indexアクションのCSRF対策を除外する
1
2
3
4
5
6
7
8
9
10
class UsersController < ApplicationController
  protect_from_forgery except: :index # 追加する
  def index
    respond_to do |format|
      format.html { binding.pry }
      format.json { binding.pry }
      format.js { binding.pry }
    end
  end
end

そして、以下の動画のように「localhost:3000/users.js」へアクセスすると、Pryが起動しformat.jsの箇所で処理が止まります。

JS形式の場合のリクエストのフォーマット

そして、request.formatを実行すると「localhost:3000/users.js」で送信されたリクエストのフォーマットがJS形式だと分かります。

これによって、format.jsに記述する処理(binding.pry)が実行されます。そして、今回もターミナルでexitを実行するとPryが終了して、対応するindex.js.erbが呼び出されます。

ポイント
  1. format.形式では、その形式のリクエストが送信されると処理が実行されます。
  2. format.形式の後に特定の処理がない場合は、Railsの仕組みとしてアクションに対応するViewファイルが呼び出されます。
  3. (例:HTML形式でリクエストがindexアクションに送信された場合は、index.html.erbが呼び出される)

処理の流れ

次に、各形式ごとの処理の流れについて整理します。
先ほど処理の箇所には全てbinding.pryを記述してましたが、各形式の処理を以下のように記述します。

app/controllers/users_controller.rb | 各形式の処理を追加する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class UsersController < ApplicationController
  def index
    @users = [
      { name: "田中", age: 22 },
      { name: "伊藤", age: 19 }
    ]

    respond_to do |format|
      format.html { redirect_to root_path }
      format.json { render json: @users }
      format.js { render 'shared/index.js.erb' }
    end
  end
end

それでは、どのような流れで上記の処理が実行されるのか全体を把握できるように形式ごとに解説します。

HTML形式の処理

HTML形式のフォーマットでリクエストが送信された場合は、format.htmlでは以下の{ redirect_to root_path }のように、redirect_toメソッドでルートにページ遷移させます。

app/controllers/users_controller.rb | HTML形式でリクエストされた場合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class UsersController < ApplicationController
  def index
    @users = [
      { name: "田中", age: 22 },
      { name: "伊藤", age: 19 }
    ]

    respond_to do |format|
      format.html { redirect_to root_path }  # この処理が実行される
      format.json { render json: @users }
      format.js { render 'shared/index.js.erb' }
    end
  end
end

HTML形式のリクエストが送信されると、本来はRailsの仕組みとしてアクションに対応するusers/index.html.erbファイルが呼び出されますが、上記の処理を記述することで以下の画像のようにルートに指定してあるusers/top.html.erbのファイルが呼び出されます。

ルートに呼び出すファイルを指定する

それでは、実際に「localhost:3000/users」にアクセスして確認します。

HTML形式の場合の処理の流れ

上記の動画よりHTML形式のフォーマットでリクエストを送信すると、ルートにリダイレクトされてusers/top.html.erbが表示されています。

URLもlocalhost:3000/usersではなくlocalhost:3000とルートのURLが表示されていることがわかります。

HTML形式の処理の流れ

上記のターミナルで確認してもusers/index.html.erbではなく、users/top.html.erbがレンダリングされています。

他にも、以下のように他の形式は処理が記述されていますが、HTML形式の処理は何も記述してないパターンが多くあります。

app/controllers/users_controller.rb | HTML形式に特定の処理を記述しない場合
1
2
3
4
5
6
7
8
class UsersController < ApplicationController
  def index
    respond_to do |format|
      format.html 
      format.js { render 'shared/index.js.erb' }
    end
  end
end

HTML形式でリクエストされた場合は特定の処理を実行する事なく、index.html.erbがRailsによって呼び出されるだけなのでformat.htmlの記載は特に必要ないように見えますが、JS形式だけではなく、HTML形式でもリクエストを受け取る場合は必要な記述になります。

app/controllers/users_controller.rb | format.htmlを削除した場合
1
2
3
4
5
6
7
class UsersController < ApplicationController
  def index
    respond_to do |format|
      format.js { render 'shared/index.js.erb' }
    end
  end
end

もし、上記のコードのようにformat.htmlがないのに「localhost:3000/users」にアクセスした場合は、以下の動画のようにエラーが発生します。

format.htmlの記述がない場合

特に処理を記述する必要がなくても、HTML形式でリクエストを受け取りたい場合はformat.htmlを記述するようにしましょう。

JSON形式の処理

JSON形式のフォーマットでリクエストが送信された場合は、format.jsonでは以下の{ render json: @users }のように、renderメソッドのjsonオプション@usersのデータをJSON形式のデータに変換して返します。

app/controllers/users_controller.rb | JSON形式でリクエストされた場合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class UsersController < ApplicationController
  def index
    @users = [
      { name: "田中", age: 22 },
      { name: "伊藤", age: 19 }
    ]

    respond_to do |format|
      format.html { redirect_to root_path }
      format.json { render json: @users } # この処理が実行される
      format.js { render 'shared/index.js.erb' }
    end
  end
end

それでは、実際に「localhost:3000/users.json」にアクセスして確認します。

JSON形式の処理の流れ

上記の動画よりJSON形式のフォーマットでリクエストを送信すると、@usersのデータがJSON形式のデータに変換されて表示されています。

WebアプリケーションではWeb APIなど、JSON形式のデータを扱う事が多いので覚えておきましょう。

JS形式の処理

JS形式のフォーマットでリクエストが送信された場合は、format.jsでは以下の{ render 'shared/index.js.erb' }のように、shared/index.js.erbのファイルがレンダリングされます。

app/controllers/users_controller.rb | JS形式でリクエストされた場合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class UsersController < ApplicationController
  def index
    @users = [
      { name: "田中", age: 22 },
      { name: "伊藤", age: 19 }
    ]

    respond_to do |format|
      format.html { redirect_to root_path }
      format.json { render json: @users }
      format.js { render 'shared/index.js.erb' } # この処理が実行される
    end
  end
end

JS形式のリクエストが送信されると、本来はRailsの仕組みとしてアクションに対応するusers/index.js.erbファイルが呼び出されますが、上記の処理を記述することで以下の画像のようにshared/index.js.erbのファイルが呼び出されます。

Viewファイルの構成

それでは、実際に「localhost:3000/users.js」にアクセスして確認します。

JS形式の処理の流れ

上記の動画よりJS形式のフォーマットでリクエストを送信すると、shared/index.js.erbが表示されています。

ターミナルでJS形式の結果を確認

上記のターミナルで確認してもusers/index.js.erbではなく、shared/index.js.erbがレンダリングされています。

この記事のまとめ

  • respond_toメソッドを使えば、リクエストされるフォーマットごとに処理を分ける事が出来る
  • format.形式と記述する事でその形式ごとの処理を記述する事が出来る
  • リクエストされるフォーマットは、request.formatで調べられる

2

わかった!