Rails3とjQueryでAjax更新

セレクトボックスを選択したら非同期通信でDBを更新する

セレクトボックスを変更した時点で非同期通信でDB更新、最新の状態を表示する。
formの:remote => true のようにボタンを用いないAjaxの実装。
一覧画面でステータスのみを更新したり、フィルター機能をボタンを押下せずに実現する。

View1 index.html.erb
<h1>注文リスト</h1>
<div id="order_list" style="display: inline;">
  <%= render :partial => 'list_body' %>
</div>
View2 部分テンプレート _list_body.html.erb

option:中身はモデルに定義。
onchange:セレクトボックスの値を変更すると指定したJSが呼び出される。

<table>
  <thead>
    <tr><th>状態</th><th>お届け先住所</th></tr>
  </thead>
  <tbody>
    <% @orders.each do |order| %>
  <tr>
    <td><%= select(:order, :"status_#{order.id}", Order::ORDER_STATUS, {:selected => order.status}, {:onchange => "update_status(\'#{order.id}\')"}) %></td>
    <td><%= order.address %></td>
  </tr>
<% end %>
  </tbody>
</table>
JavaScript order.js(viewのonchangeで指定したJSを定義。Ajaxでサーバのアクションを呼び出し。)

dataで変更されたデータのIDと、ステータスの値を定義。&区切り。
element:変更されたセレクトボックスのid
$(element).val():val()で選択されたoptionの値を取得

function update_status(o_id) {
  var element = "#order_status_" + o_id
  $.ajax({
        url: "/order/update_status", 
        type: "POST", 
        data: 'id=' + o_id + '&status=' + $(element).val()
   })
}
Controller

JSのdata内で定義された値はparamsで取得可。

def update_status
    order = Order.find_by_id(params[:id])
    order.update_attributes!(:status => params[:status])
    @orders = Order.all 
end
update_status.js.erb (jQueryになってrjsではなくなりました。)

View1の更新する箇所の要素のidとその中身となる部分テンプレートを記述。
escape_javascriptでrender以降が解釈されるようにする。

$("#order_list").html("<%= escape_javascript(render 'list_body', :orders => @orders) %>");