2019/12/03追記
Rails 6.0.x 版を書きました ↓
Rails 6.0.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のテンプレを作成後,
class AjaxTestController < ApplicationController
def top
# NOP.
end
end
Topページ用のActionを追加します.
Route Config
Controller+Actionを実装したので,Route ConfigにRoutingを追加します.
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です.
<!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/
にアクセスすると,↓ のようなページが表示されるはずです.
ただし,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に追加します.
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は ↓ のようなシンプルなものです.
Callback Msg = <%= results[:message] %>
このPartialで<div id="updated_by_ajax" >
の中身を差し替えます.
Coffee Script (Java Script)
Back EndからのAjax Callbackを受信する部分です.
$ ->
$('#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が標準でサポートされなくなったとかあるらしく,自分で設定する必要があるらしい.
//= require jquery
//= require rails-ujs
//= require turbolinks
//= require_tree .
のようにapplication.js
に//= require jquery
を追加.
このままだとcouldn't findでerrorになるので,
gem 'jquery-rails'
を追加してbundle install
してから再度rails s
すると,期待通りの動作をするようになるはず.
まとめ
素のRails 5.xの状態から最小CodeでAjaxを動作させるところまでのサンプルです.
ぼくみたいな街の組み込み屋はWeb Techに疎いので,本線一直線なシンプルなサンプルがあると助かります.
---///