更新日:
【Rails】 respond_toメソッドの使い方まとめ
respond_toメソッドとは、リクエストで指定されたフォーマットによって処理を分ける事が出来るメソッドです。
respond_toメソッドは、以下のように記述する事でリクエストされるフォーマット(HTML形式、JSON形式など)によって処理を分ける事が出来ます。
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形式に変換されたユーザーのデータが表示されます。
そして、特にフォーマットが指定されてない「localhost:3000/users」にアクセスした場合は、以下の動画のようにリクエストされるフォーマットはHTML形式になるのでformat.html
が実行されます。
format.html
の後に処理がない場合は、以下のindexアクションに対応する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.形式
と記述すると、指定した形式ごとに処理を分ける事が出来ます。
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で調べてみましょう。
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
の箇所で処理が止まります。
そして、リクエストされる形式を調べてくれる「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
の箇所で処理が止まります。
先ほどの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対策に引っ掛かりエラーが発生するので、以下のコードを追加します。
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
の箇所で処理が止まります。
そして、request.format
を実行すると「localhost:3000/users.js」で送信されたリクエストのフォーマットがJS形式だと分かります。
これによって、format.js
に記述する処理(binding.pry
)が実行されます。そして、今回もターミナルでexit
を実行するとPryが終了して、対応するindex.js.erb
が呼び出されます。
処理の流れ
次に、各形式ごとの処理の流れについて整理します。
先ほど処理の箇所には全てbinding.pry
を記述してましたが、各形式の処理を以下のように記述します。
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メソッドでルートにページ遷移させます。
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形式のフォーマットでリクエストを送信すると、ルートにリダイレクトされてusers/top.html.erb
が表示されています。
URLもlocalhost:3000/users
ではなくlocalhost:3000
とルートのURLが表示されていることがわかります。
上記のターミナルで確認してもusers/index.html.erb
ではなく、users/top.html.erb
がレンダリングされています。
他にも、以下のように他の形式は処理が記述されていますが、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形式でもリクエストを受け取る場合は必要な記述になります。
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」にアクセスした場合は、以下の動画のようにエラーが発生します。
特に処理を記述する必要がなくても、HTML形式でリクエストを受け取りたい場合はformat.html
を記述するようにしましょう。
JSON形式の処理
JSON形式のフォーマットでリクエストが送信された場合は、format.json
では以下の{ render json: @users }
のように、renderメソッドのjsonオプションで@users
のデータを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形式のフォーマットでリクエストを送信すると、@users
のデータがJSON形式のデータに変換されて表示されています。
WebアプリケーションではWeb APIなど、JSON形式のデータを扱う事が多いので覚えておきましょう。
JS形式の処理
JS形式のフォーマットでリクエストが送信された場合は、format.js
では以下の{ render 'shared/index.js.erb' }
のように、shared/index.js.erb
のファイルがレンダリングされます。
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
のファイルが呼び出されます。
それでは、実際に「localhost:3000/users.js」にアクセスして確認します。
上記の動画よりJS形式のフォーマットでリクエストを送信すると、shared/index.js.erb
が表示されています。
上記のターミナルで確認してもusers/index.js.erb
ではなく、shared/index.js.erb
がレンダリングされています。
この記事のまとめ
- respond_toメソッドを使えば、リクエストされるフォーマットごとに処理を分ける事が出来る
format.形式
と記述する事でその形式ごとの処理を記述する事が出来る- リクエストされるフォーマットは、
request.format
で調べられる