TodoList: 複数の詳細を一括更新2007年01月12日 11時55分51秒

今度は詳細 (Description) を編集出来るようにする。

まず、edit.rhtml に submit_tag を付けて、フォームを使えるようにする。


% cvs diff app/views/todo/edit.rhtml
--- app/views/todo/edit.rhtml   10 Jan 2007 05:24:08 -0000      1.4
+++ app/views/todo/edit.rhtml   10 Jan 2007 05:36:39 -0000
@@ -10,9 +10,12 @@
   <%= submit_tag 'Add' %>
 <%= end_form_tag %>
 
-<table>
-  <%= render :partial => 'add2', :collection => @todo.descriptions %>
-</table>
+<%= start_form_tag :action => 'update_descriptions', :id => @todo %>
;
+  <table>
+    <%= render :partial => 'add2', :collection => @todo.descriptions %>
+  </table>
+  <%= submit_tag 'Update' %>
+<%= end_form_tag %>
 
 <%= render :partial => 'published' %>

_add2.rhtml を書き直した。:nameを配列として生成する様に出来たので、controller 内での一括更新が容易に出来る様になった。


% cat app/views/todo/_add2.rhtml
<%= error_messages_for 'description' %>

<tr id="description_<%= add2.id %>" >

  <!--[form:description]-->
  <td>
    <label for="descriptions_<%= add2.id %>_description">Description (
    <%= Language.find(add2.language_id).name %>
    ):
    </label>
  </td>
  <td>
    <%= text_field 'descriptions', 'description',
      :id => "descriptions_" + add2.id.to_s() + "_description",
      :name => "descriptions[" + add2.id.to_s() + "][description]",
      :value => add2.description %>
  </td>
  <td>
    <%= link_to 'Destroy',
      #{ :action => 'destroy', :id => todo },
      { :action => 'destroy_description', :id => add2.id },
      :confirm => 'Are you sure?', :post => true %>
  </td>
  <!--[eoform:description]-->
 
</tr>

最後に、todo_controller.rb。上でも述べたが、詳細 (Description) が配列として、送り返されてくる。単純に、各要素を更新して、データベースに保存するだけだ。


% cvs diff app/controller/todo_controller.rb
--- app/controllers/todo_controller.rb  9 Jan 2007 04:27:15 -0000       1.13
+++ app/controllers/todo_controller.rb  10 Jan 2007 05:20:35 -0000
@@ -54,6 +54,16 @@
     @todo.descriptions << desc if desc.description.length() != 0
   end

+  def update_descriptions
+    @todo = Todo.find(params[:id])
+    @params[:descriptions].each { | desc_id, attr |
+      desc = Description.find(desc_id)
+      desc.update_attributes(attr)
+      desc.save
+      }
+    redirect_to :action => 'show', :id => @todo
+  end
+  
   def update
     @todo = Todo.find(params[:id])
     if @todo.update_attributes(params[:todo])

レコードの変更をデータベースに反映した後に、show.rhtml に飛ぶ。edit.rhtml に飛んでもいいかもしれない。

複数の詳細情報 (Description) の一括更新も容易に出来る。もう少し欲を言うのならば、変更された物のみをデータベースに保存できればよう。負荷の軽減にもつながる。それに、テーブルに更新日があった時でも、変更されていないレコードの日付まで更新する事が無くなる。

前回次回