Rails4 表形式で複数同時に更新

表形式のデータを複数同時に更新したかった。
ちょっと苦戦したのでメモ。

routes.rbでルーティングの設定

resources :evaluations, only: [:edit, :update]
get 'evaluations', :to => 'evaluations#edit', :as => :evaluations_edit
post 'evaluations', :to => 'evaluations#update'

コントローラのeditは下記の通り

def edit
  @evaluations = Evaluation.includes(:menu).
                            where(:user_id => current_user.id)
end

edit.html.erbは下記の通り

<h1>評価</h1>

<%= form_tag :action => 'update' do %>
  
  <div class="field">
    <table>
      <thead>
        <tr>
          <th>メニュー</th>
          <th>点数</th>
          <th>コメント</th>
        </tr>
      </thead>

      <tbody>
        <% @evaluations.each do |evaluation| %>
          <tr>
            <td><%= evaluation.menu.name %></td>
            <td><%= number_field_tag("evaluation[][score]", evaluation.score) %></td>
            <td><%= text_area_tag("evaluation[][comment]", evaluation.comment) %></td>                                                                    :group_id => self_evaluation_hash[:group_id] %></td>
          </tr>
          <%= hidden_field_tag("evaluation[][id]", evaluation.id) %>
        <% end %>
      </tbody>
    </table>
  </div>

  <div class="actions">
    <%= submit_tag "登録" %>
  </div>
<% end %>

<%= link_to 'トップページに戻る', root_path %>

コントローラのupdateは下記の通り

  def update
    evaluations = params[:evaluation]

    respond_to do |format|
      if Evaluation.update_evaluations(evaluations)
        format.html { redirect_to root_path }
      else
        @evaluations = Evaluation.includes(:menu).
                                  where(:user_id => current_user.id)
        format.html { render action: 'edit' }
      end
    end
  end

モデルの関数は下記の通り

def update_evaluations(evaluations)
  begin
    self.transaction do        
      evaluations.each do |evaluation_hash|
        evaluation = self.find(evaluation_hash[:id])
        evaluation.score = evaluation_hash[:score]
        evaluation.comment = evaluation_hash[:comment]

        evaluation.save!
      end
    end
    return true
  rescue
    return false
   end        
end


参考:
プログラマのオッサンの唄: Railsで表形式のデータを複数同時に更新するサンプル