digifacture

Railsとかデジモノとか色々勉強した事とか作った事とか気になった事とか

Head First Railsで詰まったとこ:Rails3でAjax更新(remote_form_forの代替)

現在Head First Railsで勉強中にAjaxでの更新で詰まったのでメモ。

手元の開発環境はRails3.2.9だけど教本はRails2を前提に書かれているので、所々コードを自分で修正しなければならない。

その中でも7章p285の新規予約登録フォームの送信から、登録一覧の表示を非同期で更新する処理の実装は苦労したので書き記したい。

それもRails2ではremote_form_forとpartialだけで実装出来るが、Rails3ではremote_form_forが廃止されているので、画面の更新をjavascriptで呼び出す必要がある。

 

Head First Rails Cap.7 p287 (Rails2)での書き方

本では下記の2点を変更するだけで良かった。

/flights/_new_seat.html.erb

<% remote_form_for(seat, :update=>'seats')> do |f| %>

/controllers/seats_controller.rb

def create
@seat = Seat.new(params[:seat])
@seat.save
render :partial => "flights/seat_list", :locals=>{:seats=>@seat.flight.seats}
end 

Rails3での書き方

まず_new_seatからform_seatにオプションを渡せるように:seat=>seat追記する。

/views/flights/_new_seat.html.erb

<h1>New seat</h1>

<%= render 'form_seat', :seat=>seat %>

<%= link_to 'Back', seats_path %> 

 form_forのsubmitをAjax(XHR)で送信するように :remote=>trueを追記する。

 /views/flights/_form_seat.html.erb

<%= form_for(seat, :remote=>true) do |f| %>

Ajaxでリクエストが来た場合に、jsでレスポンスを返すためにformat.jsを加筆する。 

/controllers/seats_controller.rb

def create
  @seat = Seat.new(params[:seat])
  respond_to do |format|
    if @seat.save
      format.html { render :partial => "flights/seat_list", :locals=>{:seats=>@seat.flight.seats} }
      format.json { render json: @seat, status: :created, location: @seat }
      format.js

    else
      format.html { render action: "new" }
      format.json { render json: @seat.errors, status: :unprocessable_entity }
    end
  end
end

 コントローラからcreateアクションを実行する際に、create.js.erbを新たに作成する。ここで新しく登録された予約のあるデータを<%= "/flights/#{@seat.flight.id}/seats" %>を参照して、jQueryにてページの一覧を書き換える。

/views/seats/create.js.erb

$.ajax(
  {
    type: 'GET',
    url: '<%= "/flights/#{@seat.flight.id}/seats" %>',
    dataType: 'html',
    success: function(data) {
      $('#seats').html(data);
    },
    error:function() {
      alert('Ajax Error');
    }
  }

);

 上記のように書けばフォームを入力し、submitボタンを押すと新しく登録したデータが予約の一覧に非同期で追加されるのをみることができる。

 

ポイントはform_forにremote=>trueすることでXMRによる送信になり、controllerはXMRでは.jsで返す仕組みがある、ということなのだろう。

ちゃんとcontrollerの動きや、HTTPの仕組みを把握しなければ理解できないことが多そう。

ツギハギだらけで不十分なことだらけだけど、Head First Railsで同じようにハマった人の助けになれば幸いです。

O'Reilly Japan - Head First Rails

参考:(他にもたくさんあるけど抜粋)

Rails3のAjaxでHTMLを返してjQueryで処理する - #詰んでる日記

Rails3で特定のid要素の中身をAjaxで書き換える - (゚∀゚)o彡 sasata299's blog

Sebastián González : Rails 4: How to partials & AJAX, dead easy

Rails3の form_for で Ajax をやってみた - KodaNote

Rails 3 で remote_form_for みたいなことをやる - RunoLog

Ruby Learning Notes: Replacement for remote_form_for in Rails 3 ←ここのやり方が1番

uu59のメモ | RailsとJS(vue.js)の連携

教訓:コピペしてもコードの意味がわからないとダメダメね