2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RailsでのAjax処理

Posted at

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-remotetrueに変更し、他のパラメーターもdata-***で指定します。
Rubyの処理内なのでurlの指定にはset_sample_pathみたいな変数がそのまま使えます。
また、コントローラーに渡すデータは、テキストボックスならvalue属性が、セレクトボックスならselected optionが自動的に設定されます。
その他のデータを渡したい場合、data { params: 'id=' + @sample.id, type: 'json' }のような感じで設定すればOK。

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

Controller

def set_sample
  # データ更新などの処理
  result = {
    event: 'sample',
    data: ...
  }
  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で処理が識別できます。
しまった、eventeventeventがかぶってしまった。
ページ内に複数のAjax処理があるとswitchなどを使って受信処理を分岐させる必要があります。
しかし失敗時の処理は分岐させる必要がないなど、状況に応じて共通化させることもできます。

余談

最近、Napstablookという保有投資信託管理サービスをリリースしました。
本記事はNapstablookの開発中にAjax処理が必要になったため、調べてまとめたものになります。
Napstablookではセレクトボックスやテキストボックスが変更されたときにAjax通信を開始し、コントローラーでデータの更新や計算を行った後、ビューにデータを返すという処理を行っています。

さらに余談

AUTOVICEという私のポートフォリオサイトでRailsの技術情報の記事を書いていますので、よければこちらもご覧ください。
そろそろ独自ドメインに移行したい。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?