Edited at

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

More than 1 year has passed since last update.


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に疎いので,本線一直線なシンプルなサンプルがあると助かります.

---///