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