new.html.erb
とedit.html.erb
で以下のようにform_for
を使用し、データの保存、変更を行いたい!
new.html.erb
とedit.html.erb
で同じフォームを使用していたら、formの部分を丸ごとパーシャルにしておしまいなのですが・・・
現在、開発しているとこではnew.html.erb
とedit.html.erb
で使用しているフォームが一部異なるため、まるまる共通化できません。
そこで、合致している部分だけ共通化し、異なる部分は条件分岐で切り分けようということで、その方法を忘れないように記したいと思います。
まず、new.html.erb
の方はこんな感じです。
<%= form_for(@user, :url => {:action => 'create'} ) do |f| %>
<%= render :partial => 'error_message' %>
<table>
<tr>
<td><%= f.label :ユーザーID %></td>
<td><%= f.text_field :user_id %></td>
</tr>
<tr>
<td><%= f.label :画像ID %></td>
<td><%= f.text_field :photo_id %></td>
</tr>
<tr>
<td><%= f.label :配信日 %></td>
<td><%= f.text_field :open_date %></td>
</tr>
</table>
<%= f.submit "登録" %>
<% end %>
edit.html.erb
は以下の通りです。
<%= form_for(@user, :url => {:action => 'update'} ) do |f| %>
<%= render :partial => 'error_message' %>
<table>
<tr>
<td><%= f.label :ユーザーID %></td>
<td><%= f.text_field :user_id %></td>
</tr>
<tr>
<td><%= f.label :画像ID %></td>
<td><%= f.text_field :photo_id %></td>
</tr>
<tr>
<td><%= f.label :配信日 %></td>
<td><%= f.text_field :open_date %></td>
</tr>
<tr>
<td><%= f.label :表示順位 %></td>
<td><%= f.text_field :visible_order %></td>
</tr>
</table>
<%= f.submit "更新" %>
<% end %>
<%= render :partial => 'error_message' %>
<table>
<tr>
<td><%= f.label :ユーザーID %></td>
<td><%= f.text_field :user_id %></td>
</tr>
<tr>
<td><%= f.label :画像ID %></td>
<td><%= f.text_field :photo_id %></td>
</tr>
<tr>
<td><%= f.label :配信日 %></td>
<td><%= f.text_field :open_date %></td>
</tr>
切り分けたい部分は以下です。
<tr>
<td><%= f.label :表示順位 %></td>
<td><%= f.text_field :visible_order %></td>
</tr>
</table>
<%= f.submit "更新" %>
<% end %>
</table>
<%= f.submit "登録" %>
<% end %>
1. 現在いるURLを参照し切り分ける方法
まず、_form.html.erb
を作成し、request.path_info
で現在いるURLを参照し、そのURLによってレイアウトを切り分けます。
こんな感じです。
<%= render :partial => 'error_message' %>
<table>
<tr>
<td><%= f.label :ユーザーID %></td>
<td><%= f.text_field :user_id %></td>
</tr>
<tr>
<td><%= f.label :画像ID %></td>
<td><%= f.text_field :photo_id %></td>
</tr>
<tr>
<td><%= f.label :配信日 %></td>
<td><%= f.text_field :open_date %></td>
</tr>
<% if request.path_info = edit_users_path %>
<tr>
<td><%= f.label :表示順位 %></td>
<td><%= f.text_field :visible_order %></td>
</tr>
</table>
<%= f.submit "更新" %>
<% else %>
</table>
<%= f.submit "登録" %>
<% end %>
<%= form_for(@user, :url => {:action => 'create'} ) do |f| %>
<%= render :partial => 'form', :locals => {:f => f} %>
<% end %>
<%= form_for(@user, :url => {:action => 'update'} ) do |f| %>
<%= render :partial => 'form', :locals => {:f => f} %>
<% end %>
非常にすっきりしました。
<% if request.path_info = edit_users_path %>
によって、editページでformが呼び出されたらレイアウト1を表示し、それ以外のページで表示されたら場合は<% else %>
以下のレイアウト2が表示されます。
切り分けるページが2つと限られていたらこの方法でも対応できます。
2. renderに引数を渡して切り分ける方法
_form.html.erb
の方で、<% if local_assigns[:edit_flag].present? %>
を使用し、partialの指定したローカル変数に値が入っているか否かを判別し切り分ける方法です。
この条件分岐をすることで、レイアウト1を使用したいページのhtmlにrender :partial => 'form' :locals = >{ :f => f, :edit_flag => true}
と定義するとどのページでもレイアウト1のフォームが適用されます。
_form
は以下の通りです。
<%= render :partial => 'error_message' %>
<table>
<tr>
<td><%= f.label :ユーザーID %></td>
<td><%= f.text_field :user_id %></td>
</tr>
<tr>
<td><%= f.label :画像ID %></td>
<td><%= f.text_field :photo_id %></td>
</tr>
<tr>
<td><%= f.label :配信日 %></td>
<td><%= f.text_field :open_date %></td>
</tr>
<% if local_assigns[:edit_flag].present? %>
<tr>
<td><%= f.label :表示順位 %></td>
<td><%= f.text_field :visible_order %></td>
</tr>
</table>
<%= f.submit "更新" %>
<% else %>
</table>
<%= f.submit "登録" %>
<% end %>
各ページのhtmlは以下の通りです。
<%= form_for(@user, :url => {:action => 'create'} ) do |f| %>
<%= render :partial => 'form', :locals => {:f => f} %>
<% end %>
<%= form_for(@pickup_client, :url => {:action => 'update'}) do |f| %>
<%= render :partial => 'form', :locals => {:f => f, :edit_flag => true} %>
<% end %>
この切り分けのメリットとしては、各ページで使いたいレイアウト用にrenderの引数を定義すれば良いので、partialをいじる必要がなく、保守性が高いという点にあります。