Ruby on Railsでは、HTMLフォームから送信されたデータをコントローラーで受け取り、JSON形式でレスポンスを返すことができます。この仕組みは、Ajax通信を使った非同期処理やAPIエンドポイントの構築で頻繁に使われます。この記事では、フォームの作成からデータの受け取り、JSON応答の返却までの流れを解説します。
基本的な使い方
まず、フォームを含むビューとデータを受け取るコントローラーアクション、ルーティングを設定します。
Rails.application.routes.draw do
get "test" => "test#index"
post "test/submit" => "test#submit"
endclass TestController < ApplicationController
def index
end
def submit
name = params[:name]
render json: { success: true, message: name }
end
endrender json:を使うと、RubyのハッシュをJSON形式に変換してレスポンスとして返します。ブラウザやJavaScriptからは{"success":true,"message":"入力値"}のようなJSONデータを受け取ることができます。
フォームの作成
ビューにHTMLフォームを作成します。Ajax送信を行う場合は、通常のフォーム送信を防止してJavaScriptで処理します。
<form id="myForm">
<label for="name">名前</label>
<input type="text" name="name" id="name">
<button id="submitBtn" type="button">送信</button>
</form>
<div id="result"></div>JavaScriptでAjax送信
Fetch APIを使って、フォームのデータを非同期でサーバーに送信し、JSON応答を受け取ります。
document.getElementById("submitBtn").addEventListener("click", function() {
const name = document.getElementById("name").value;
const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
fetch("/test/submit", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken
},
body: JSON.stringify({ name: name })
})
.then(response => response.json())
.then(data => {
document.getElementById("result").textContent = data.message;
})
.catch(error => {
console.error("Error:", error);
});
});RailsではCSRFトークンの検証がデフォルトで有効になっています。Ajax通信を行う場合は、metaタグからトークンを取得して、リクエストヘッダーのX-CSRF-Tokenに含める必要があります。
Strong Parametersの使用
実際のアプリケーションでは、Strong Parametersを使って受け取るパラメータを制限するのが推奨されます。
class TestController < ApplicationController
def submit
permitted = params.permit(:name, :email, :age)
if permitted[:name].present?
render json: {
success: true,
data: {
name: permitted[:name],
email: permitted[:email],
age: permitted[:age]
}
}
else
render json: {
success: false,
error: "名前は必須です"
}, status: :unprocessable_entity
end
end
endparams.permitで許可するパラメータを明示的に指定することで、不正なパラメータの送信を防ぎます。バリデーションエラーの場合はstatus: :unprocessable_entity(422)を返すのが一般的です。
モデルと連携したJSON応答
データベースへの保存と組み合わせた実践的な例も見てみましょう。
class PostsController < ApplicationController
def create
@post = Post.new(post_params)
if @post.save
render json: {
success: true,
post: {
id: @post.id,
title: @post.title,
created_at: @post.created_at.strftime("%Y/%m/%d %H:%M")
}
}, status: :created
else
render json: {
success: false,
errors: @post.errors.full_messages
}, status: :unprocessable_entity
end
end
private
def post_params
params.require(:post).permit(:title, :content)
end
endAPIとして使う場合は、ApplicationControllerの代わりにActionController::APIを継承するとよいでしょう。CSRFトークンの検証が不要になるなど、API専用の軽量なコントローラーが使えます。
CSRFトークンの検証を無効にするskip_before_action :verify_authenticity_tokenは、セキュリティ上のリスクがあるため、やむを得ない場合にのみ使用してください。
まとめ
render json:でRubyのハッシュをJSON形式で返せる- Ajax通信にはFetch APIを使い、
X-CSRF-Tokenヘッダーを含める - Strong Parametersで受け取るパラメータを制限してセキュリティを確保する
- 成功時は
:created(201)、エラー時は:unprocessable_entity(422)のステータスを返す - モデルのバリデーションエラーは
errors.full_messagesで取得してJSON応答に含める - API専用コントローラーには
ActionController::APIを使用する