RailsでのAjax処理

2019年10月10日 21:35

    Ajax on jQuery

    jQueryでAjax処理を書くと以下のような感じになります。
    <input type="textbox" id="sample" />
    
    <script>
      $(function() {
        $('#sample').on('change', function() {
          $.ajax({
            type: 'POST',
            url: '/funds/set_category',
            data: { category: $(this).val,
            dataType: 'json'
          }).done(function(data, textStatus, jqXHR) {
            // 成功時の処理
          }).fail(function(jqXHR, textStatus, errorThrown) {
            // 失敗時の処理
          }).always(function() {
            // 結果にかかわらず実行される処理
          });
        });
      });
    </script>
    Ajax通信を開始する処理にメソッドチェーンで成功時の処理や失敗時の処理を付け足していきます。
    成功時の処理や失敗時の処理を書いていくと、JavaScriptの部分がどんどん肥大化していくことになります。

    Ajax on Rails

    Railsでは以下のように書くことができます。
    <%= text_field_tag 'sample', data: { remote: true,
                                         method: 'POST',
                                         url: set_sample_path } %>
    
    <script>
      document.body.addEventListener('ajax:success', function(event) {
        // 成功時の処理
      });
      document.body.addEventListener('ajax:error', function(event) {
        // 失敗時の処理
      });
      document.body.addEventListener('ajax:complete', function(event) {
        // 結果にかかわらず実行される処理
      });
    </script>
    少しすっきりした気がします。
    data-remoteをtrueに変更し、他のパラメーターもdata-***で指定します。
    Rubyの処理内なのでurlの指定にはset_sample_pathがそのまま使えます。
    また、コントローラーに渡すデータは、テキストボックスならvalue属性が、セレクトボックスならselected optionが自動的に設定されます。
    その他のデータを渡したい場合、data { params: 'id=' + fund.id, type: 'json' }のような感じで設定すればOK。

    ひとつ注意があります。
    例ではページ内にAjax処理を行う場所がひとつだけなので、結果を受け取る処理もひとつだけで大丈夫です。
    しかし、Ajax処理を行う場所が複数あると、処理の種類によって結果を受け取る処理を変えなければなりません。
    具体的な方法については次のセクションで説明します。

    Controller

    def set_sample
      // データ更新などの処理
      result = {
        event: 'sample',
        data: samples
      }
      render json: result, status: 200
    end
    データとステータスコードを返却します。
    このとき、データの中にどの処理かが識別できる情報を入れておきます。例ではevent: 'sample'の部分です。
    また、ステータスコードを設定しないとビューでの受信時にデータの形がおかしくなるので必ず設定します。

    Re:View

    <script>
      document.body.addEventListener('ajax:success', function(event) {
        // 成功時の処理
        var data = event.detail[0];
        switch(data.event) {
          'sample':
            // 処理
            break;
          ...
        }
      });
      ...
    </script>
    再びビューの処理です。
    コントローラー側から受信した返却データはevent.detail[0]の中に入っています。
    さらに今回はJSON形式でeventというパラメーターを設定しているので、event.detail[0].eventで処理が識別できます。
    しまった、eventとeventでeventがかぶってしまった。
    ページ内に複数のAjax処理があるとswitchなどを使って受信処理を分岐させる必要があります。
    しかし失敗時の処理は分岐させる必要がないなど、状況に応じて共通化させることもできます。

    関連記事

    関連記事はありません。