Ruby on Rails - メソッド(Action)の Ajax 化!

Updated:


Ruby on Rails で Submit ボタンを押下後に画面遷移することなく部分的に表示を更新する方法についての備忘録です。

ちなみに、以前は別のアプローチで Rails + jQuery の Ajax 化(遅延読み込み)の記事を紹介しています。

0. 前提条件

  • Rails 4.1.0 での作業を想定。
  • jQuery 導入済みであることを想定。(但し、通常の JavaScript でも代替可能のはず)
  • Form の Submit ボタン押下でメソッド(Controller の Action)を呼び、結果を部分的に View(部分テンプレート)に反映させることを想定。
    (Submit ボタン押下に限らず、リンククリックの場合も同様)

1. 準備

以下のような View テンプレートがあるとする。(説明用に簡素な例)
(「検索」ボタン押下で、 “HogeContller” の “fuga” Action が呼ばれ、検索結果は下部の div 要素に表示される)
(以下の div 要素内で使用する “_fuga_dtl.html.erb” のソースコードは割愛)

File: app/views/hoge/fuga.html.erb

1
2
3
4
5
6
7
<%= form_tag({controller: "hoge", action: "fuga"}) do %>
  <%= submit_tag("検索", name: nil) %>
<% end %>

<div id="fuga-dtl">
  <%= render :partial => 'fuga_dtl' %>
</div>

div 要素内は、後述の “js.erb” で更新するので通常不要であるが、当方の場合は検索時のみでなく初期表示でも使用するので記述している)

また、以下のような Controller があるとする。(説明用に簡素な例)

File: app/controllers/hoge_controller.rb

1
2
3
4
5
6
7
8
class HogeController < ApplicationController
  def fuga

    # ===< 何かしらの処理 >===

    # render での返却はなし
  end
end

2. 既存 View テンプレート(html.erb ファイル)の編集

View テンプレートを以下のように編集する。(data: {remote: true} 部分を追記)
(ちなみに、旧バージョンの Rails なら :remote => true だろう)

File: app/views/hoge/fuga.html.erb

1
2
3
4
5
6
7
<%= form_tag({controller: "hoge", action: "fuga"}, {data: {remote: true}}) do %>
  <%= submit_tag("実行", name: nil) %>
<% end %>

<div id="fuga-dtl">
  <%= render :partial => 'fuga_dtl' %>
</div>

3. Ajax 用テンプレート(js.erb ファイル)の作成

Ajax 処理用のテンプレート(js.erb ファイル)を以下のように作成する。(名前は html.erb ファイルと同じ)
(jQuery で id が fuga-dtl である要素に “_fuga_dtl.html.erb” をレンダリングした結果を HTML として埋め込む、ということ)

File: app/views/hoge/fuga.js.erb

1
$('#fuga-dtl').html('<%= j(render("fuga_dtl")) %>');

jQuery でなく通常の JavaScript なら以下のようになるだろう。(当方未確認)

File: app/views/hoge/fuga.js.erb

1
document.getElementById('fuga-dtl').innerHTML('<%= j(render("fuga_dtl")) %>');

(ちなみに、 j メソッドは escape_javascript ヘルパのエイリアス)

4. 動作確認

動作確認をしてみる。

Submit ボタンを押下後に画面全体が更新されることなく、部分的に更新されるようになるはずである。

5. その他

最初から存在していた “fuga.html.erb” と この “fuga.js.erb” と2つのテンプレートが存在することになるが、 Ajax 処理(Ajax リクエスト)の場合は “js” で取り扱われるため、 Controller 内では特に何も変更していない。

意図的に Controller 内で Ajax リクエストか否かを判定したい場合は、以下のようにすればよいだろう。

class HogeController < ApplicationController

  if request.xhr?
    # Ajax リクエストの場合の処理 ( true の場合 )
  else
    # その他の場合の処理 ( false の場合 )
  end

end

ページ全体が更新されない(ページが部分的に更新される)ので若干軽くなり、また視覚的も新鮮な感じがします。

以上。





 

Sponsored Link

 

Comments