カテゴリ: Rails 更新日: 2026/02/03

Railsで非同期リクエストを使いこなそう!初心者でもわかるTurbo・fetch APIとコントローラ設計の基本

非同期リクエスト対応:Turbo/ fetch API とコントローラ設計の要点
非同期リクエスト対応:Turbo/ fetch API とコントローラ設計の要点

先生と生徒の会話形式で理解しよう

生徒

「Railsで、ボタンを押したときだけ部分的にページを更新する方法ってありますか?全部の画面を再読み込みしたくないです。」

先生

「その場合は非同期リクエストが便利ですよ。Turboやfetch APIを使えば、ページ全体をリロードせずに動きのあるアプリが作れます。」

生徒

「非同期って難しそうですね……」

先生

「大丈夫です!Railsでは仕組みが整っているので、初心者でも扱いやすいんですよ。順番に解説していきましょう!」

1. 非同期リクエストとは?

1. 非同期リクエストとは?
1. 非同期リクエストとは?

非同期リクエストとは、ページ全体を更新するのではなく、一部分だけをサーバーと通信して書き換える技術のことです。英語ではAJAX(エージャックス)とも呼ばれます。

例えば、「いいねボタンを押したときに、その部分だけカウントが増える」といった動作が可能になります。これにより、ユーザー体験(UX)が大きく向上します。

2. Rails 7からのTurboとは?

2. Rails 7からのTurboとは?
2. Rails 7からのTurboとは?

Turboは、Rails 7で導入された標準の非同期通信ツールです。JavaScriptを書かなくても、HTMLだけで非同期リクエストを実現できるのが特徴です。

たとえば、以下のようにフォームにdata-turbo-frameを指定するだけで、自動で部分的な更新が可能になります。


<turbo-frame id="comment_form">
  <%= form_with model: @comment do |f| %>
    <%= f.text_area :content %>
    <%= f.submit "投稿" %>
  <% end %>
</turbo-frame>

これだけで、フォームを送信してもページ全体をリロードせずに、新しいコメントだけが反映されます。

3. Turboを使うときのコントローラ設計

3. Turboを使うときのコントローラ設計
3. Turboを使うときのコントローラ設計

Turboを使った場合、通常のHTMLとTurbo用のレスポンスを切り分けることがポイントです。


def create
  @comment = Comment.new(comment_params)
  if @comment.save
    respond_to do |format|
      format.turbo_stream
      format.html { redirect_to post_path(@comment.post) }
    end
  else
    render :new
  end
end

format.turbo_streamとすることで、Railsは自動でcreate.turbo_stream.erbというテンプレートを探して表示してくれます。

4. fetch APIとは?JavaScriptで非同期通信する方法

4. fetch APIとは?JavaScriptで非同期通信する方法
4. fetch APIとは?JavaScriptで非同期通信する方法

fetch APIは、ブラウザに標準搭載されているJavaScriptの機能で、手動で非同期リクエストを送ることができます。

Turboではできない複雑な動作をしたいときや、APIと連携する場面で活躍します。


<button id="like-btn">いいね!</button>

<script>
document.getElementById("like-btn").addEventListener("click", () => {
  fetch("/likes", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-CSRF-Token": document.querySelector("meta[name='csrf-token']").content
    },
    body: JSON.stringify({ post_id: 1 })
  })
  .then(response => response.json())
  .then(data => {
    alert(`現在のいいね数: ${data.count}`);
  });
});
</script>

5. fetch API用のRailsコントローラ設計

5. fetch API用のRailsコントローラ設計
5. fetch API用のRailsコントローラ設計

fetch APIで通信する場合、Rails側のコントローラではrender json:を使ってJSON形式で返すようにします。


def create
  like = Like.create(post_id: params[:post_id])
  render json: { count: Like.where(post_id: params[:post_id]).count }
end

これで、JavaScript側にデータが返され、動的に画面に反映させることができます。

6. Turboとfetch APIの使い分けポイント

6. Turboとfetch APIの使い分けポイント
6. Turboとfetch APIの使い分けポイント
  • Turbo:フォームや部分更新がシンプルなとき。JavaScript不要。
  • fetch API:細かい動作やアニメーション、API連携が必要なとき。

どちらも非同期通信を実現する手段ですが、用途に応じて適切に選ぶことが大切です。

7. 非同期対応でRailsアプリはもっと快適に

7. 非同期対応でRailsアプリはもっと快適に
7. 非同期対応でRailsアプリはもっと快適に

非同期通信を取り入れることで、Railsアプリケーションはページの切り替えが少なくなり、動きのある快適な操作感を提供できます。

Turboやfetch APIを理解して使いこなすことで、今までよりもぐっと使いやすいアプリを作れるようになります。コントローラ設計も、レスポンス形式を意識するだけなので初心者にも優しい仕組みです。

これをきっかけに、あなたのRailsアプリにもインタラクティブな非同期機能を取り入れてみましょう!

まとめ

まとめ
まとめ

これまでに学んできたRailsにおける非同期リクエストの仕組み、Turboやfetch APIの活用方法、そしてそれらを支えるコントローラ設計について、重要なポイントを振り返ってみましょう。非同期通信は、現代のWebアプリケーション開発において、ユーザーにストレスを与えないスムーズな操作性(UX)を提供するために欠かせない技術です。

非同期通信のメリットとRailsの親和性

ページ全体をリロードする「同期通信」とは異なり、「非同期通信」は必要なデータだけを背後でやり取りします。Rails 7からはHotwire(Turbo/Stimulus)が標準搭載されたことで、複雑なJavaScriptを大量に記述しなくても、Railsらしい直感的なコードで高度な非同期処理が実装できるようになりました。

特に、データベースの情報を更新しつつ、その結果を即座に画面の一部へ反映させる処理は、RailsのMVCモデルと非常に相性が良いです。ここでは、具体的なデータベース操作とSQL、そしてRubyコードを交えて、一連の流れを詳しく見ていきましょう。

データベース操作とコントローラでの実装例

例えば、記事に対する「いいね(Like)」機能を実装する場合を考えます。まずは現在のデータベースの状態を確認しましょう。


id | user_id | post_id | created_at
---+---------+---------+--------------------
1  | 10      | 101     | 2026-01-25 10:00:00
2  | 11      | 101     | 2026-01-25 10:05:00
3  | 12      | 102     | 2026-01-25 10:10:00
4  | 13      | 101     | 2026-01-25 10:15:00

ここで、新しい「いいね」が追加された際のRailsコントローラの動きをSQLと共に追ってみます。Turboを利用する場合、RailsはHTMLの断片(Turbo Stream)を返却します。


# app/controllers/likes_controller.rb
class LikesController < ApplicationController
  def create
    @post = Post.find(params[:post_id])
    @like = @post.likes.build(user_id: current_user.id)

    if @like.save
      respond_to do |format|
        # Turbo用のレスポンス
        format.turbo_stream
        # 非同期非対応ブラウザ用のフォールバック
        format.html { redirect_to @post }
      end
    end
  end
end

このとき、バックエンドでは以下のようなSQLが発行され、データベースが更新されます。


INSERT INTO likes (user_id, post_id, created_at, updated_at) 
VALUES (14, 101, '2026-01-30 17:00:00', '2026-01-30 17:00:00');

SELECT COUNT(*) 
FROM likes 
WHERE post_id = 101;

実行後のデータベースの状態は以下のようになります。


id | user_id | post_id | created_at
---+---------+---------+--------------------
1  | 10      | 101     | 2026-01-25 10:00:00
2  | 11      | 101     | 2026-01-25 10:05:00
3  | 12      | 102     | 2026-01-25 10:10:00
4  | 13      | 101     | 2026-01-25 10:15:00
5  | 14      | 101     | 2026-01-30 17:00:00

fetch APIを活用した柔軟なデータ取得

一方で、JavaScript側でより緻密な制御を行いたい場合は、fetch APIを利用してJSONデータを取得します。例えば、特定のユーザー情報を動的に取得して表示するようなケースです。


# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
    render json: { 
      id: @user.id, 
      name: @user.name, 
      status: "Active" 
    }
  end
end

JavaScript側での呼び出し例:


async function fetchUserInfo(userId) {
  const response = await fetch(`/users/${userId}`, {
    method: 'GET',
    headers: {
      'Accept': 'application/json'
    }
  });
  const data = await response.json();
  console.log("取得したユーザー:", data.name);
}

適切な技術選定のために

Rails開発において、非同期リクエストの実装手段を選ぶ基準はシンプルです。

  • Turbo Drive / Turbo Frames: ページ遷移を高速化したい、あるいは特定のHTML要素を差し替えたい。
  • Turbo Streams: フォーム送信後に複数の箇所を同時に更新したい、あるいはリアルタイムな通知を実現したい。
  • fetch API (with Stimulus): Railsの枠組みを超えた複雑なUI操作や、外部APIとの通信、JSONデータを元にしたグラフ描画などを行いたい。

これらのツールを組み合わせることで、開発効率を維持したまま、モダンなシングルページアプリケーション(SPA)に近い体験をユーザーに提供することが可能になります。まずはTurboから触れてみて、必要に応じてfetch APIを導入していくというステップが、Rails初心者にとっては最もスムーズな習得への近道と言えるでしょう。

先生と生徒の振り返り会話

生徒

「先生、まとめを読んで非同期リクエストの使い分けがかなり明確になりました!基本的にはTurboを使って、HTMLをそのままやり取りするのがRails流なんですね。」

先生

「その通りです。Rails 7からは『JavaScriptをなるべく書かない』という方向性が強まっています。Turbo Framesを使えば、特定の範囲だけを切り取って更新できるので、コードがとてもスッキリしますよ。」

生徒

「でも、さっきのfetch APIの例みたいにJSONを返してJSで処理する場合も、やっぱり現場では使われますか?」

先生

「もちろんです。例えば、地図アプリでピンの情報を動的に変えたり、複雑なチャートを表示したりするときはJSONの方が扱いやすいんです。大切なのは、何でもかんでもJSでやろうとせず、Railsが用意してくれた強力なTurbo機能をまずは信じて使い倒すことですね。」

生徒

「なるほど!まずはTurboで実装してみて、どうしても表現が足りない時にfetch APIやStimulusを検討する、という優先順位でやってみます!」

先生

「素晴らしい心がけですね。Railsのコントローラ側で format.turbo_stream を使う感覚に慣れてくると、Webアプリ作りがもっと楽しくなりますよ。ぜひ自分のプロジェクトでも、小さな『いいねボタン』から非同期化に挑戦してみてください。」

関連記事:
カテゴリの一覧へ
新着記事
New1
Ruby
Rubyの文字エンコーディング入門!UTF-8・マジックコメント・外部/内部エンコーディングを完全解説
New2
Rails
Rails GoodJob入門!PostgreSQLベースのバックグラウンド処理を初心者向けに完全解説
New3
Ruby
Rubyで学ぶビット演算入門:&・|・^・~・<<・>>の基礎と実例
New4
Rails
RESTとRailsの関係を徹底解説!resources設計と7つの標準アクションを初心者向けにわかりやすく解説
人気記事
No.1
Java&Spring記事人気No1
Ruby
Rubyのreduceとinject入門!合計計算や集計を初心者向けに分かりやすく解説
No.2
Java&Spring記事人気No2
Ruby
Rubyの始め方ガイド:インストールから最初のHello Worldまで(Windows/Mac/Linux)
No.3
Java&Spring記事人気No3
Ruby
Rubyの文字列エンコーディング完全ガイド!Encoding・force_encoding・encodeを初心者向け解説
No.4
Java&Spring記事人気No4
データベース
PostgreSQLのWHERE句を徹底解説!初心者でもわかるSQLデータ抽出の基本
No.5
Java&Spring記事人気No5
Ruby
Rubyのfind/detect/find_indexを徹底解説!目的のデータを素早く探す方法
No.6
Java&Spring記事人気No6
Ruby
Rubyで比較演算子を完全解説!==・===・<=>・eql? の使い分け
No.7
Java&Spring記事人気No7
Ruby
Rubyのselect/reject/filterの使い方を完全解説!初心者向けの条件抽出レシピ
No.8
Java&Spring記事人気No8
データベース
PostgreSQLで順位付け!ROW_NUMBER関数の使い方を初心者向けに徹底解説