前回のサンプルで、更新に加えて削除もできるように改修を行った。
今回は、同じ画面から新規追加も行えるようにしてみたい。
rails g scaffold imp2_ramen name:string price:integer rake db:migrate新規追加のために、add_rowというルートを新たに追加。それ以外は前回から変更なし。
match '/imp2_ramen/add_row' => 'imp2_ramen#add_row' match '/imp2_ramen/update_all' => 'imp2_ramen#update_all' match '/imp2_ramen/confirm_all' => 'imp2_ramen#confirm_all' match '/imp2_ramen/edit_all' => 'imp2_ramen#edit_all', as: 'edit_all_imp2_raman', :via => :get resources :imp2_ramencontrollerの確認画面(confirm_all)の箇所を下記のように編集。
パラメーターとしてIDが飛んで来なければ、新規追加と判断してクラスをnewしている。
# GET /imp2_ramen/confirm_all
def confirm_all
@imp2_ramen = Array.new
for imp2_raman in params[:imp2_ramen]
unless imp2_raman["id"].blank?
updated_imp2_raman = Imp2Raman.find(imp2_raman["id"])
updated_imp2_raman.update_attributes(imp2_raman)
@imp2_ramen << updated_imp2_raman
else
@imp2_ramen << Imp2Raman.new(imp2_raman)
end
end
session[:imp2_ramen] = @imp2_ramen
end
今回追加したadd_rowというルートのcontroller側の記述は下記の通り。実は何もしていない(笑)。
クライアント側のJavaScriptだけで完結することも可能なのだが、Railsの<%~%>タグが使いたいので、一度サーバに飛ばすようにしている。
# GET /imp2_ramen/add_row
def add_row
respond_to do |format|
format.js { render :layout => false }
end
end
複数同時更新画面(edit_all)のviewは下記の通り。「行追加」のボタンを追加したことと、新規の場合はチェックボックスの代わりに「新規」という文字を表示するようにしたことが変更点。
<h1>Editing all imp2_ramen</h1>
<%= form_tag :action => 'confirm_all' do %>
<table border="1">
<tr>
<th>新規/削除</th>
<th>Name</th>
<th>Price</th>
</tr>
<% for imp2_raman in @imp2_ramen %>
<tr>
<td>
<% unless imp2_raman.id.blank? %>
<%= hidden_field_tag("imp2_ramen[][id]", imp2_raman.id) %>
<%= check_box_tag("imp2_ramen[][delete_check]", true, imp2_raman.delete_check) %>
<% else %>
<%= '新規' %>
<% end %>
</td>
<td>
<%= text_field_tag("imp2_ramen[][name]", imp2_raman.name) %>
</td>
<td>
<%= number_field_tag("imp2_ramen[][price]", imp2_raman.price) %>
</td>
</tr>
<% end %>
</table>
<%= submit_tag "入力確認" %>
<input id="add_row_button" type="button" value="行追加" />
<% end %>
<%= link_to 'Back', imp2_ramen_path %>
「行追加」のボタンがクリックされると、app/assets/javascript/imp2_ramen.js.coffeeで、下記の処理を実行。クリックを検知して、ajaxとしてadd_row.jsのpathを読みに行くだけ。
jQuery ->
jQuery('#add_row_button').click ->
$.get("add_row.js")
add_row.jsは下記の内容となる。tableの最後に空行を追加している。
$('tbody').append('<tr><td>新規</td><td><%= text_field_tag("imp2_ramen[][name]") %></td><td><%= number_field_tag("imp2_ramen[][price]") %></td></tr>')
このファイルではなく、前述のimp2_ramen.js.coffee内でinputタグを直接記述すれば同じことができるはずなのだが、Railsの場合はinputタグ内のidの付け方が独特なので、保守性を考慮してview側と同様の記述(<%~%>)を行うようにしている。確認画面(confirm_all)のviewは下記の通り。
<h1>Editing all imp2_ramen</h1>
<table border="1">
<thead>
<tr>
<th>新規/削除</th>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<% for imp2_raman in @imp2_ramen %>
<tr>
<td>
<% if imp2_raman.delete_check %>
<%= '削除' %>
<% elsif imp2_raman.id.blank? %>
<%= '新規' %>
<% end %>
</td>
<td>
<%= imp2_raman.name %>
</td>
<td>
<%= imp2_raman.price %>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= form_tag :action => 'update_all' do %>
<%= submit_tag "更新" %>
<% end %>
<%= link_to 'Back', edit_all_imp2_raman_path %>
IDが存在しない場合に、「新規」と表示している以外は前回から変更なし。controller側で新規追加分も含めてImp2Ramanクラスの配列としてセッションに格納しているので、view側では同じ配列をループさせて値を取り出すのみ。
実際の画面遷移の例は以下のようになる。
一覧画面(index)
更新画面(edit_all)
更新画面(edit_all)で新規追加。
確認画面(confirm_all)
更新後の一覧画面(index)
今回作成したソースコードの参照はこちらから。
https://github.com/torafugu/mytest/blob/master/app/assets/javascripts/imp2_ramen.js.coffee
https://github.com/torafugu/mytest/tree/master/app/views/imp2_ramen
https://github.com/torafugu/mytest/blob/master/app/controllers/imp2_ramen_controller.rb













