Rails 5.x標準で Ajax+(jQuery+Partial) でHTML部分更新する世界一シンプルなサンプル

TL;DR (長い3行で)

Ajaxの勉強をするにあたり,Rails上でAjaxするためのサンプルを探していたのですが,Rails 5.xがもともとテンプレとして持っている.html.erb.coffeeではなく,.html.haml.js.erbを使ったものもあり,ヨコ道知識を調べながらになってしまったので,できる限りrails newした状態からの差分が少ない,世界一シンプルなサンプルコードを目指してまとめてみました.

ざっくりシーケンス

だいたい ↓ のようなシーケンスを実現します.
Client-Server間でSession張って双方向通信とかそういうところはRails Frameworkが全部やってくれているようで,Rails Developerが考える処理はとても少ないですね.

Front End : UserがInputしたTextをAjaxでBack End側にPost
↓
Back End : PostされたTextとPartialを使って部分的に差し替えるHTMLをRendering
↓
Front End : .coffee (Java Script)でAjaxのCallbackを受け取る
↓
Front End : jQueryでHTMLの部分差し替え

Project作成

いつもの ↓ のコマンドでProjectを作成+Project Dirに移動します.

$ rails new ajax_test
$ cd ajax_test

この時点で
$ rails s
でサーバ起動すると,
http://localhost:3000/
にアクセスしてDefaultのRootページが表示されます.

Static Page作成

Ajax実装のベースになるStatic Pageを実装します.

Controller

$ rails g controller AjaxTest
でControllerのテンプレを作成後,

app/controlles/rajax_test_controller.rb
class AjaxTestController < ApplicationController
  def top
    # NOP.
  end
end

Topページ用のActionを追加します.

Route Config

Controller+Actionを実装したので,Route ConfigにRoutingを追加します.

config/routes.rb
root  to: 'ajax_test#top'
post  'ajax_test/update', to: 'ajax_test#update', as: 'ajax_test_update'

Topページ表示用のRoute(root)とAjaxのRequest Post用のRouteの2本を追加しています.

View

ControllerとRouteができたので,残りはViewです.

app/views/ajax_test/top.html.erb
<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <div id="request_ajax_update" >
      <%= form_tag(ajax_test_update_path, method: :post, remote: true) { %>
        <%= text_field :data, :text %>
        <%= submit_tag 'Post AJAX' %>
      <% } %>
    </div>

    <hr>
    <div id="updated_by_ajax" >
      DEFAULT
    </div>
    <hr>
  </body>
</html>

大きく2つのブロックだけです.

<div id="request_ajax_update" >
Ajax RequestをPostするFormを持つブロック.
Userが入力したTextをparams[:data][:text]に詰めて,ajax_test/updateにPostします.

<div id="updated_by_ajax" >
Ajax Callbackを受けてHTMLの部分更新をするブロック.

この時点で,http://localhost:3000/にアクセスすると,↓ のようなページが表示されるはずです.

top_default.png

ただし,Ajaxの実装がまだ無いので,Post AJAXボタンをClickしても ↓ のようなエラーになります.(ControllerにActionの実装がない)

Started POST "/ajax_test/update"
AbstractController::ActionNotFound (The action 'update' could not be found for AjaxTestController):

Ajax実装

Ajax本体シーケンスの実装です.
さっき作ったStatic PageにAjax用の実装を追加していきます.

Controller

Ajax RequestのPostを受けるupdateのActionをControllerに追加します.

app/controllers/ajax_test_controller.rb
class AjaxTestController < ApplicationController
  def top
    # NOP.
  end

  def update
    post_text = params[:data][:text]
    results = { :message => post_text }
    render partial: 'ajax_partial', locals: { :results => results }
  end
end

Partial

Update Actionの中でRenderingしているPartialは ↓ のようなシンプルなものです.

app/views/ajax_test/_ajax_partial.html.erb
Callback Msg = <%= results[:message] %>

このPartialで<div id="updated_by_ajax" >の中身を差し替えます.

Coffee Script (Java Script)

Back EndからのAjax Callbackを受信する部分です.

app/assets/javascripts/ajax_test.coffee
$ ->
  $('#request_ajax_update')
    .on 'ajax:complete', (event) ->
      response = event.detail[0].response
      $('#updated_by_ajax').html(response)

Ajaxのcomplete callbackで渡されるeventはXMLHttpRequestの型の配列で,
event.detail[0].response
にBack End側でRenderingして返した部分HTMLが格納されています.
この部分HTMLをjQueryを使って差し替えます.

ただし,このままでTopページからPost AJAXをClickしても何も起こらない.
ChromeのDeveloper ToolでConsole Logをみると,

Uncaught ReferenceError: $ is not defined

というLogが出ている.
$が定義されていない = JQueryが使えていない,らしい.

jQueryを使えるようにする

Rails 5.xからjQueryが標準でサポートされなくなったとかあるらしく,自分で設定する必要があるらしい.

app/assets/javascripts/application.js
//= require jquery
//= require rails-ujs
//= require turbolinks
//= require_tree .

のようにapplication.js//= require jqueryを追加.
このままだとcouldn’t findでerrorになるので,

Gemfile
gem 'jquery-rails'

を追加してbundle installしてから再度rails sすると,期待通りの動作をするようになるはず.

top_ajax.png

まとめ

素のRails 5.xの状態から最小CodeでAjaxを動作させるところまでのサンプルです.
ぼくみたいな街の組み込み屋はWeb Techに疎いので,本線一直線なシンプルなサンプルがあると助かります.

—///

関連記事