目次
開発環境
- 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <div class="wrapper"> <div class="container flex-start"> <div class="col-box-1"> <h2>メモ一覧</h2> </div> <div class="col-box-1"> <%= render "layouts/errors", obj: @memo_new %> </div> <div class="col-box-3"> <%= render "memos/form", memo_new: @memo_new %> </div> <%= render "memos/list", memos: @memos %> </div> </div> |
非同期通信の実装に必要なJSライブラリを設定する
今回、Rails7で非同期通信の実装に必要なJSライブラリを設定します。
1 2 3 4 5 6 7 8 9 10 11 | <!DOCTYPE html> <html> <head> <title>MemoApp</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <%= csrf_meta_tags %> <%= csp_meta_tag %> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/@rails/ujs@6.0.2/lib/assets/compiled/rails-ujs.js"></script> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> </head> |
「jquery」と「rails-ujs」をそれぞれCDNで読み込む設定をします。
非同期通信のルーティングを作成する
続いて、非同期通信のルーティングを作成します。
1 2 3 4 5 6 7 8 9 | Rails.application.routes.draw do root :to => 'memos#index' resources :memos, only: [:index, :update, :destroy, :create] post 'ajax_memos_create', to: 'memos#ajax_create', as: 'ajax_memos_create' # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html # Defines the root path route ("/") # root "articles#index" end |
HTTPSメソッドがPOSTで「ajax_memos_create」のURLがリクエストされた場合に、memosコントローラー内のajax_createアクションを呼び出します。
また、「as: 'ajax_memos_create'」とすることにより、名前付きルートを固定する形になります。
コントローラーに非同期通信で処理する内容を記述する
続いて、コントローラーに非同期通信で処理する内容を記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | class MemosController < ApplicationController def index @memo_new = Memo.new @memos = Memo.all end def create @memo_new = Memo.new(memos_params) @memos = Memo.all if @memo_new.save redirect_to root_path else render action: "index" end end def update @memo = Memo.find(params[:id]) @memo.update(memos_params) redirect_to root_path end def destroy @memo = Memo.find(params[:id]) @memo.destroy redirect_to root_path end def ajax_create @memo_new = Memo.new(memos_params) @memo_new.save @memos = Memo.all end private def memos_params params.require(:memo).permit(:title, :description) end end |
Ruby on RailsではJS形式でリクエストされた場合、処理が終わった後は「アクション名.js.erb」ファイルを探してくれます。
もちろん、renderメソッドでファイルを指定することもできますが、今回は割愛しています。
非同期通信により処理が実行された後のJSファイルを記述する
続いて、非同期通信により処理が実行された後のJSファイルを「memo_app\app\views\memos」フォルダ内に作成して記述します。
1 2 3 | $('#memo-list').html("<%= j(render "memos/list", memos: @memos) %>"); $('#errors').html("<%= j(render "layouts/errors", obj: @memo_new) %>"); $('#memo-post').find('.form-box').val(''); |
js.erbのJSファイル内にRubyの記述でコードを書きこめる便利な拡張子です。
今回は1行目で一覧表示を再度読み込む、2行目でエラーメッセージを再度読み込む、3行目で新規投稿フォーム内の値を空にするという内容になっています。
ただ、エスケープ処理をしてかなければならないため、Rubyのescape_javascriptメソッドを利用して「j()」や「escape_javascript()」としておく必要があります。
非同期通信するためにセレクタのIDをインデックスビューに設定する
続いて、非同期通信するためにセレクタのIDをインデックスビューに設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <div class="wrapper"> <div class="container flex-start"> <div class="col-box-1"> <h2>メモ一覧</h2> </div> <div class="col-box-3" id="memo-post"> <%= render "memos/form", memo_new: @memo_new %> </div> <div class="col-box-2" id="errors"> <%= render "layouts/errors", obj: @memo_new %> </div> </div> <div class="container flex-start" id="memo-list"> <%= render "memos/list", memos: @memos %> </div> </div> |
それぞれ新規投稿フォーム、エラーメッセージ、一覧表示にIDを付与しておき、JSファイルで処理する場所を指定しておきます。
新規投稿フォームを非同期通信にする
最後に新規投稿フォームを非同期通信にします。
1 2 3 4 5 6 7 8 9 10 11 | <%= form_with model: memo_new, url: ajax_memos_create_path, local: false, method: :post do |f| %> <div class="memo-header"> <%= f.text_field :title, placeholder: "タイトル", class: "form-box" %> </div> <div class="memo-center"> <%= f.text_area :description, placeholder: "メモ", class: "form-box" %> </div> <div class="memo-footer"> <%= f.submit "作成", class: "btn" %> </div> <% end %> |
form_withの場合は「local: false」のオプションを追加することにより、フォームのプロパティに「data-remote="true"」を追加することができます。
また、非同期通信用のルーティングを作成しておりますので、「ajax_memos_create_path」に変更しておきます。
以上でURLが変わらずにデータの処理が非同期通信で行えていれば実装完了です。
おわりに
Ruby on Railsで非同期通信について解説してきましたが、いかがだったでしょうか。
今回は新規投稿とエラーメッセージ、一覧表示に対して非同期通信の実装をしましたが、編集機能や更新機能、削除機能はもちろん、フラッシュメッセージにも実装することが可能です。
是非、ユーザーがアプリケーションを使いやすいようにするためにも、非同期通信の実装にチャレンジにしてみてください。