はじめに
RailsのAjaxを使って特定の要素を編集・更新する方法について記載します。
例で簡単なカテゴリー一覧画面の1つのカテゴリーの名前を更新する処理を使います。
バージョン
- ruby 2.6.3
 - rails 5.2.1
 
画面概要
この右のほうにある鉛筆マークの編集アイコンボタンを押すと、該当の行のカテゴリー名がフォームに変わります。

変更後のカテゴリー名にデータが更新され、表示を非同期で変更します。
例では、「交通」→「交通費」に変更します。

処理概要
- 
要素にAjaxのためのオプションを追加
link_toにremote: trueオプションをつけます。 - 
Ajaxするためのルーティングを追加
 - 
コントローラやモデルでオブジェクトの取得または更新
 - 
追加したアクションのためのJavaScript用のviewファイルを用意し、画面の該当の要素を変更するためのJavaScriptを記載
 
実装前
実装前の主要なコード部分は以下になります。
def index
  @categories = Category.where(user: current_user).order(:created_at)
end
<ul class="todo-list" id="own-categories">
  <% @categories.each do |category| %>
    <li id="category-list-id-<%= category.id %>">
      <%= render 'a_category_list', category: category %>    
    </li>
  <% end  %>
</ul>
<span class="handle ui-sortable-handle">
  <i class="fa fa-ellipsis-v"></i>
  <i class="fa fa-ellipsis-v"></i>
</span>
<span class="text"><%= category.name %></span>
<%= category.common_mark %>
<div class="tools">
  <%= link_to edit_category_path(category), class: "text-redpepper space-left" do %>
    <i class="fa fa-lg fa-edit"></i>
  <% end %>
  <%= category.common_btn %>
</div>
カテゴリー名を編集するフォームに変更するAjax処理の実装
鉛筆マークの編集アイコンボタンを押下して、カテゴリー名の要素をフォーム要素に変更する処理を記載していきます。
※注意:説明しないclass属性やid属性などがありますが、Ajax処理とは関係ありません。
1. Ajaxするためのオプションを追加
編集アイコンボタンにremote: trueを仕込む。
<%= link_to edit_category_path(category), remote: true, class: "text-redpepper space-left" do %>
  <i class="fa fa-lg fa-edit"></i>
<% end %>
2. Ajaxするためのルーティングを追加
Ajaxするときでも、ルーティングのresourcesメソッドが柔軟に対応してくれます。
ここでは、editアクションを追加します。
resources :categories, only: [:index, :edit]
3. コントローラでオブジェクトの取得
def edit
  @category = Category.find(params[:id])
end
4. 追加したアクションのためのJavaScript用のviewファイルを用意し、画面の該当の要素を変更するためのJavaScriptを記載
editアクションなので、app/views/categories/edit.js.erbを作成します。
id = "<%= @category.id %>";
target = document.querySelector(`#category-list-id-${id}`);
html = "<%= j(render partial: 'form', locals: { category: @category }) %>";
target.innerHTML = html;
<%= form_with(model: category) do |form| %>
  <div class="row">
    <div class="col-xs-10">
      <div class="input-group input-group-sm">
        <%= form.text_field :name, value: category.name, required: true, class:"form-control", max: 15 %>
        <span class="input-group-btn">
          <%= form.submit submit_btn_letters, class: "btn btn-brown" %>
        </span>
      </div>
    </div>
    <div class="col-xs-1">
      <%= category.cancel_btn %>
    </div>
  </div>
<% end %>
これで、カテゴリー名を編集するためのフォームが表示できます。

カテゴリー名を更新するAjax処理の実装
編集フォームに変更できたので、次に、変更したい文字「交通費」に変更して、
更新ボタンを押下し、更新後のカテゴリー名を表示する処理を記載していきます。
1. Ajaxするためのオプションを追加
form_withにremote: trueオプションを追加します。
(明示的に記載しなくてもデフォルトでremote: trueにはなっている。)
<%= form_with(model: category, remote: true) do |form| %>
  <!-- 省略 -->
<% end %>
2. Ajaxするためのルーティングを追加
updateアクションを追加
resources :categories, only[:index, :edit, :update]
3. コントローラでオブジェクトの更新
カテゴリー名を「交通費」で更新します。
def update
  @category = Category.find(params[:id])
  @category.update(category_params)
end
private
def category_params
  params.require(:category).permit(:name, :is_common)
end
4. 追加したアクションのためのJavaScript用のviewファイルを用意し、画面の該当の要素を変更するためのJavaScriptを記載
編集フォームを更新したカテゴリー名に変更する処理を行います。
updateアクションなのでapp/views/categories/update.js.erbを作成します。
id = "<%= @category.id %>";
target = document.querySelector(`#category-list-id-${id}`);
html = "<%= j(render partial: 'categories/a_category_list', locals: { category: @category }) %>";
target.innerHTML = html;
おわりに
JavaScriptでAjax処理を書いてもいいのですが、シンプルなAjaxはRailsであれば簡単にできます。
ただ、〇〇.js.erbの書き方は癖が強いので要注意です。


