LoginSignup
29
29

More than 3 years have passed since last update.

2019年にRails + Ajaxを整理してみる(サンプルアプリ&コード付き)

Last updated at Posted at 2019-06-22

Rails上でAjaxを動かす、という良くありそうな話。

ただ調べてみるとやり方が色々あって、
Rails歴半年ちょいの私には何が正しいのかさっぱり分からなかった。

という訳で整理してみる。同じ境遇にある人の助けになれば嬉しい。

jQueryとかを用いた、古式ゆかしい(らしい)やり方ですので、
Vue/React等をお使いの方々はおかえりください(涙)

間違ってる部分とかあったら、コメントいただければ幸いです。
(特に図の部分)

この記事がよく刺さりそうな人

  • Railsの基礎はわかる
  • Ajaxの雰囲気はわかる
  • JavaScript & jQueryも本気出せばちょっと書ける
    (決してチョットデキルではない)
  • RailsでAjaxはあまりやった事がない
    もしくは「良く分からんけどまぁ動いてるからヨシ!」で乗り切った

とりあえず結論

Rails + Ajax の実現方法は、
ざっくり以下の3パターン&その組み合わせっぽい。

1. Rails推奨方式
2. フロントはJavaScriptだけでやる方式
3. AjaxのリクエストはRails & レスポンス以降はJavaScriptでやる方式

方式別サンプルアプリ&コード

作ったのは、フォームに文字を入力&ボタンを押すと、Ajaxを使って文字が書き換わるアプリ。
(アプリを名乗るのはおこがましいかもしれない)

これを上の3方式のそれぞれでやってみた。
Ajaxでやる意味ある?というツッコミは無しで...

ajax-succeed.gif

コードは本当に必要最低限なので、色々細かいツッコミはご容赦くださいm(_ _)m
逆に手元で再現する分にはやりやすいはず。。。

あとjQueryを使ってます。入れ方は以下参照。
Rails 5.2 jQuery 動かし方 - Qiita

共通処理

サーバ(Rails)側の処理は、3つの方式でほぼ共通。

routes.rb
Rails.application.routes.draw do
  get 'static/top'
  post 'static/ajax_update', to: 'static#ajax_update'
  post 'static/ajax_update2', to: 'static#ajax_update2'
end
static_controller.rb
class StaticController < ApplicationController
  def top
  end

  # 1. Rails推奨方式 で使用
  def ajax_update
    @text = params[:data]
    render
  end

  # 2. フロント側はJavaScriptだけでやる方式 
  # 3. AjaxのリクエストはRails & レスポンス以降はJavaScriptでやる方式
  # で使用
  def ajax_update2
    @text = params[:data]
    render plain: @text
  end
end

1. Rails推奨方式

Railsガイドに書かれたやり方
Rails で JavaScript を使用する - Rails ガイド

ajax_update.js.erb
var user = '<%= "#{ @text }" %>'
$('#ajax-test1').text(user);
top.html.slim
h1 Static#top
p Find me in app/views/static/top.html.slim

#ajax-test1 Ajax: Rails依存

#ajax-request1
  = form_with url: static_ajax_update_path do |f|
    = f.text_field :data
    = f.submit 'Post Ajax'

図に表すと多分以下の感じ。
もうガッツリRailsに乗っかっている状態。

rails-ajax.001.jpeg

肝は以下2点

  • xxx.js.erbからJavaScriptをレンダリングしてフロントに返す
  • フロント側で受け取ったJavaScriptを実行

個人的にはRails側で、JavaScriptをレンダリングしている辺り、
少し気持ち悪い。。。

ただコード量は必要最低限で済むし、
Rails推奨であることからトラブルも起きにくそう。
基本はこれでいいのではないだろうか。

なお細かい処理がしたい場合には不便になることもある様子で、
何だかんだ使わないと言う話もあるらしい。
参考:https://qiita.com/ka215/items/dfa602f1ccc652cf2888

2. フロント側はJavaScriptだけでやる方式

Railsにあえて叛逆していくやり方。

top.html.slim
#ajax-test4 Ajax: ほぼJS(jQuery)
= text_field_tag 'static[ajax_data2]'
= button_tag 'Post Ajax', id: 'btn2'
ajax_request_response.js
$(document).ready( () => {
  $('#btn2').on('click', (e) => {
    e.preventDefault();

    const param = $('#static_ajax_data2').val();

    // CSRFトークンを取得&セット
    $.ajaxPrefilter( (options, originalOptions, jqXHR) => {
        if (!options.crossDomain) {
          const token = $('meta[name="csrf-token"]').attr('content');
          if (token) {
               return jqXHR.setRequestHeader('X-CSRF-Token', token);
           }
        }
    });

   $.ajax({
      url: `/static/ajax_update2`,
      type: 'POST',
      data: {
        data: param
      }
    })
    .done( (data, textStatus, jqXHR) => {
      var result = $('#ajax-test4');
      result.text(data);
    });
  });
});

図に表すと多分以下の感じ。
Ajaxに関しては、Railsには頼らないという強い意思が見える。

rails-ajax.002.jpeg

肝は、
RailsのCSRF対策のために、
CSRFトークンの取得&セットを行なっている所。

具体的なやり方は以下の記事を完全リスペクトしましたm(_ _)m
https://qiita.com/a_ishidaaa/items/7c3fa339d3bea25a9ba8

ざっくり言うと、RailsではCSRFという脆弱性への対策として、
Postのリクエスト時にトークン(身分証明みたいなもの)を使っている。
ここをカバーしてあげないと、JavaScriptからPostは出来ない。

そう、Railsからの叛逆に成功したと思いきや、
実はその呪縛から逃れきれていなかったのだ。
なんかエモい。

なお、RailsのCSRFについての詳細は以下の記事等をご参照ください。
外部からPOSTできない?RailsのCSRF対策をまとめてみた - Qiita

3. AjaxのリクエストはRails & レスポンス以降はJavaScriptでやる方式

Railsへの依存を減らしつつ、CSRF対策はRailsによろしくできるやり方。

top.html.slim
= form_with url: static_ajax_update2_path, id: 'ajax-request-3' do |f|
  = f.text_field :data
  = f.submit 'Post Ajax'
ajax_response.js
// Ajax: form送信はRails、受信以降はJS
$( () => {
  $('#ajax-request-3').on('ajax:success', (e) => {
    const result = $('#ajax-test3');
    result.text(e.detail[0]);
  });
});

図に表すと多分以下の感じ。
折衷案な雰囲気。

rails-ajax.003.jpeg

肝は、
RailsとJavaScriptの間で、
どのようにデータをやり取りされるかの理解が必要な所。

適当にやってると変なハマり方をしそう。。。

ただそこさえクリアすれば、
Railsっぽさと自由度をある程度両立できる?気がする(よく分かってない)

まとめ

  • 基本的には大人しく「1. Rails推奨方式」を使った方がいい気がする。
    (特に経験浅めの人)
  • ただ不便な場合もある(らしい)ので、
    その際は「3. AjaxのリクエストはRails...」を採用、
    もしくは「1. Rails推奨方式」と組み合わせて使えば良さそう。
  • Railsで開発するけどなるべく依存したくないというワガママな人は、
    「2. フロント側はJavaScriptだけでやる方式」を使えばいい...のか?

参考サイト

以下本記事作成に際しお世話になったサイト。見ると理解がすごく深まる。。。
Ruby on RailsのAjax処理のおさらい - Qiita
Rails 5.1+jQueryでajaxを試す (罠にハマる) - Qiita
Rails 5.2 jQuery 動かし方 - Qiita
RailsでのAjax - Qiita
jQuery.ajax()のまとめ: 小粋空間
Rails 5.2 jQuery 動かし方 - Qiita

29
29
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
29
29