【Ruby on Rails】簡単なメモアプリの作成|非同期通信(Ajax)の実装

作成日: 更新日:

開発環境

  • Ruby:version 3.1.2
  • Ruby on Rails:version 7.0.4
  • Visual Studio Code:version 1.73.0
  • OS:Windows10

Ruby on Railsで非同期通信(Ajax)の実装手順

Ruby on Railsの非同期通信は、WebAPI、コメント、いいね機能、チャット機能、コメント機能、dm機能などでも当たり前に行われています。 今回はメモアプリの作成で使用した「新規投稿」と「エラーメッセージ」のコードを用いて解説していきます。

非同期通信を実装する前のインデックスビュー

今回、非同期通信を実装する前のインデックスビューが下記になります。

1// memo_app\app\views\memos\index.html.erb
2<div class="wrapper">
3    <div class="container flex-start">
4        <div class="col-box-1">
5            <h2>メモ一覧</h2>
6        </div>
7
8        <div class="col-box-1">
9            <%= render "layouts/errors", obj: @memo_new %>
10        </div>
11
12        <div class="col-box-3">
13            <%= render "memos/form", memo_new: @memo_new %>
14        </div>
15
16        <%= render "memos/list", memos: @memos %>
17    </div>
18</div>

非同期通信の実装に必要なJSライブラリを設定する

今回、Rails7で非同期通信の実装に必要なJSライブラリを設定します。

1// memo_app\app\views\layouts\application.html.erb
2<!DOCTYPE html>
3<html>
4  <head>
5    <title>MemoApp</title>
6    <meta name="viewport" content="width=device-width,initial-scale=1">
7    <%= csrf_meta_tags %>
8    <%= csp_meta_tag %>
9+   <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
10+   <script src="https://cdn.jsdelivr.net/npm/@rails/ujs@6.0.2/lib/assets/compiled/rails-ujs.js"></script>
11    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
12  </head>

「jquery」と「rails-ujs」をそれぞれCDNで読み込む設定をします。

非同期通信のルーティングを作成する

続いて、非同期通信のルーティングを作成します。

1// memo_app\config\routes.rb
2Rails.application.routes.draw do
3  root :to => 'memos#index'
4  resources :memos, only: [:index, :update, :destroy, :create]
5+ post 'ajax_memos_create', to: 'memos#ajax_create', as: 'ajax_memos_create'
6  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
7
8  # Defines the root path route ("/")
9  # root "articles#index"
10end

HTTPSメソッドがPOSTで「ajax_memos_create」のURLがリクエストされた場合に、memosコントローラー内のajax_createアクションを呼び出します。 また、「as: 'ajax_memos_create'」とすることにより、名前付きルートを固定する形になります。

コントローラーに非同期通信で処理する内容を記述する

続いて、コントローラーに非同期通信で処理する内容を記述します。

1// memo_app\app\controllers\memos_controller.rb
2class MemosController < ApplicationController
3  def index
4    @memo_new = Memo.new
5    @memos = Memo.all
6  end
7
8  def create
9    @memo_new = Memo.new(memos_params)
10    @memos = Memo.all
11    if @memo_new.save
12      redirect_to root_path
13    else
14      render action: "index"
15    end
16  end
17
18  def update
19    @memo = Memo.find(params[:id])
20    @memo.update(memos_params)
21    redirect_to root_path
22  end
23
24  def destroy
25    @memo = Memo.find(params[:id])
26    @memo.destroy
27    redirect_to root_path
28  end
29
30+ def ajax_create
31+   @memo_new = Memo.new(memos_params)
32+   @memo_new.save
33+   @memos = Memo.all
34+ end
35
36  private
37
38  def memos_params
39    params.require(:memo).permit(:title, :description)
40  end
41
42end

Ruby on RailsではJS形式でリクエストされた場合、処理が終わった後は「アクション名.js.erb」ファイルを探してくれます。 もちろん、renderメソッドでファイルを指定することもできますが、今回は割愛しています。

非同期通信により処理が実行された後のJSファイルを記述する

続いて、非同期通信により処理が実行された後のJSファイルを「memo_app\app\views\memos」フォルダ内に作成して記述します。

1// memo_app\app\views\memos\ajax_create.js.erb
2$('#memo-list').html("<%= j(render "memos/list", memos: @memos) %>");
3$('#errors').html("<%= j(render "layouts/errors", obj: @memo_new) %>");
4$('#memo-post').find('.form-box').val('');

js.erbのJSファイル内にRubyの記述でコードを書きこめる便利な拡張子です。 今回は1行目で一覧表示を再度読み込む、2行目でエラーメッセージを再度読み込む、3行目で新規投稿フォーム内の値を空にするという内容になっています。 ただ、エスケープ処理をしてかなければならないため、Rubyのescape_javascriptメソッドを利用して「j()」や「escape_javascript()」としておく必要があります。

非同期通信するためにセレクタのIDをインデックスビューに設定する

続いて、非同期通信するためにセレクタのIDをインデックスビューに設定します。

1// memo_app\app\views\memos\index.html.erb
2<div class="wrapper">
3    <div class="container flex-start">
4        <div class="col-box-1">
5            <h2>メモ一覧</h2>
6        </div>
7
8+       <div class="col-box-3" id="memo-post">
9            <%= render "memos/form", memo_new: @memo_new %>
10        </div>
11
12+       <div class="col-box-2" id="errors">
13            <%= render "layouts/errors", obj: @memo_new %>
14        </div>
15     </div>
16
17+    <div class="container flex-start" id="memo-list">
18        <%= render "memos/list", memos: @memos %>
19    </div>
20</div>

それぞれ新規投稿フォーム、エラーメッセージ、一覧表示にIDを付与しておき、JSファイルで処理する場所を指定しておきます。

新規投稿フォームを非同期通信にする

最後に新規投稿フォームを非同期通信にします。

1// memo_app\app\views\memos\_form.html.erb
2+ <%= form_with model: memo_new, url: ajax_memos_create_path, local: false, method: :post do |f| %>
3    <div class="memo-header">
4        <%= f.text_field :title, placeholder: "タイトル", class: "form-box" %>
5    </div>
6    <div class="memo-center">
7        <%= f.text_area :description, placeholder: "メモ", class: "form-box" %>
8    </div>
9    <div class="memo-footer">
10        <%= f.submit "作成", class: "btn" %>
11    </div>
12<% end %>

form_withの場合は「local: false」のオプションを追加することにより、フォームのプロパティに「data-remote="true"」を追加することができます。 また、非同期通信用のルーティングを作成しておりますので、「ajax_memos_create_path」に変更しておきます。 以上でURLが変わらずにデータの処理が非同期通信で行えていれば実装完了です。

おわりに

Ruby on Railsで非同期通信について解説してきましたが、いかがだったでしょうか。 今回は新規投稿とエラーメッセージ、一覧表示に対して非同期通信の実装をしましたが、編集機能や更新機能、削除機能はもちろん、フラッシュメッセージにも実装することが可能です。 是非、ユーザーがアプリケーションを使いやすいようにするためにも、非同期通信の実装にチャレンジにしてみてください。

【Ruby on Rails】簡単なメモアプリの作成|非同期通信(Ajax)の実装 | いっしー@Webエンジニア