【Rails】Ajax通信でできること1（モーダルでデータを登録する編）

どうもこんにちは。

今回は、RailsでのAjax通信について紹介をしようと思います。

ちなみに私は、Ajax通信のヘビーユーザーです。

# Ajaxとは

Ajaxとは、「Asynchronous JavaScript + XML」の略。

つまり、「JavaScriptとXMLを使用したサーバとの非同期通信」のことです。

？？？？？

# 同期通信と非同期通信

データ登録時の処理を例にして簡単に説明をすると、

同期通信は、
1. アプリのページで登録ボタンを押す
1. サーバーで登録処理を行う
1. 処理が完了したら登録後のページに遷移できる

非同期通信は
1. アプリのページで登録ボタンを押す
1. サーバーでの登録処理をしている間に他のページに遷移できる

要するに、「直列動作」か「並列動作」かですね。

# 同期通信の例（通常の動作）

同期通信での詳細な動作は以下のようになります。

1. アプリのページでフォームにデータを入力する
1. アプリのページで登録ボタンを押す
1. 登録ボタンを押されたことをトリガーにcreateメソッドが動作する
1. createメソッドで登録処理が行われる
1. 処理が完了したら登録後のページにリダイレクトする

実装は簡単で、以下のようなコードだけで足ります。

html

```erb
<%= form_for @sample_normal, url: sample_normals_path(@sample_normal) do |f| %>
    <%= f.label :sample_normals, :title %>
    <%= f.text_field :title, autocomplete: "off", class: 'form-control col-sm-10' %>
    <%= f.submit %>
<% end %>
```

controller

```ruby
def create
    @sample_normal = SampleNormal.new(sample_normal_params)
    if @sample_normal.save
        redirect_to sample_normals_path
    else
        render :new
    end
end

private

# ストロングパラメータ
def sample_normal_params
  params.require(:sample_normal).permit(:title)
end
```

# 非同期通信の例（Ajax通信の動作）

非同期通信での詳細な動作は以下のようになります。

1. モーダルでフォームにデータを入力する
1. モーダルで登録ボタンを押す
1. 登録ボタンを押されたことをトリガーにjavascriptのクリックイベントが動作する
1. javascript側で入力された情報を取得する
1. javascript側からAjax通信によってcreate_ajaxメソッドが動作する
1. create_ajaxメソッドで登録処理が行われる
1. 登録処理が終わったら結果がjavascriptに戻ってくる
1. javascript側からモーダルを閉じる

実装は同期処理よりも少し手間です。

html

```erb
<div id="sample_ajax_modal" class="modal fade show" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" style="display: none;" aria-modal="true" data-toggle="modal">
  <div class="modal-dialog modal-lg">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">タイトル追加</h4>
        <button type="button" class="closeModal close" data-dismiss="modal" aria-hidden="true">×</button>
      </div>
      <div class="modal-body p-4">
        <div class="row">
          <div class="col-md-12">
            <div class="form-group row">
              <div class="col-sm-2">
                <label class="control-label">タイトル</label>
              </div>
              <div class="col-sm-10">
                <%= text_field_tag 'sample_ajax_title', "", class: 'form-control' %>
              </div>
            </div>
          </div>
        </div>
        <button type="button" id="create_title" class="btn btn-success waves-effect waves-light pull-right ml-2 mt-2">追加</button>
        <button type="button" class="closeModal btn btn-light waves-effect waves-light pull-right ml-2 mt-2">キャンセル</button>
      </div>
    </div>
  </div>
</div>
```

javascript

```javascript
document.addEventListener('DOMContentLoaded', function() {
    // ボタンを押された時のクリックイベント
    document.getElementById('create_title').addEventListener('click', function() {
        // テキストフィールドからタイトルを取得します
        var title = document.getElementById('sample_ajax_title').value;
    
        // Ajax通信を開始します
        fetch('/sample_ajax/create_ajax', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                // RailsのCSRFトークンを設定します
                'X-CSRF-Token': document.querySelector('[name="csrf-token"]').content
            },
            body: JSON.stringify({ title: title })
        })
        .then(response => response.json())
        .then(data => {
            console.log(data);
        })
        .catch(error => {
            console.error('Error:', error);
        });
    
        # モーダルを閉じる
        $('#sample_ajax_modal').modal('hide');
    });
});

```

controller

```ruby
def create_ajax
    sample_ajax = SampleAjax.new(title: params[:title])
    respond_to do |format|
        if sample_ajax.save
            format.json { render json: 'save ok' }
        else
            format.json { render json: 'save fail' }
        end
    end
end
```

上記のように入力フォームをモーダルで表示することによって、**いちいち新規登録画面や編集画面に遷移しなくてもデータの登録、編集ができる**ようになります。
（編集の場合は、既存のデータをモーダルに表示する必要があるのでモーダルを開く際にもAjax通信を行う必要があります。）

実装は少々手間に感じるかもしれないですが、自分でデータの流れを確認しながら実装できるので、繰り返し実装していけばすぐに理解できます。

# まとめ

今回はAjax通信についてまとめてみました。

Javascriptを使用することによって、非同期処理を実現することができました。
ただし、JavaScriptを使用するときはRails側でファイルパスが通っているか確認をしてください。

`app/javascripts`ディレクトリに存在している`application.js`に直接処理を書いても良いですが、基本的には同じディレクトリにモデル名と同じ名前のjsファイルを作成して、`application.js`には`import '作成したjsファイルの相対パス'`を記述した方がよろしいかと思われます。

他にも普段使用しているhtml.erbファイルをjs.erbとすることで非同期処理を行うこともできます。
こちらについては、ページの一部を動的に更新したい時に有効な方法なので、次の記事で紹介しています。

以上