LoginSignup
83
79

More than 5 years have passed since last update.

フォームの一部を共通化

Last updated at Posted at 2014-08-28

new.html.erbedit.html.erbで以下のようにform_forを使用し、データの保存、変更を行いたい!
new.html.erbedit.html.erbで同じフォームを使用していたら、formの部分を丸ごとパーシャルにしておしまいなのですが・・・

現在、開発しているとこではnew.html.erbedit.html.erbで使用しているフォームが一部異なるため、まるまる共通化できません。
そこで、合致している部分だけ共通化し、異なる部分は条件分岐で切り分けようということで、その方法を忘れないように記したいと思います。

まず、new.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は以下の通りです。

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>

切り分けたい部分は以下です。

レイアウト1
    <tr>
      <td><%= f.label :表示順位 %></td>
      <td><%= f.text_field :visible_order %></td>
    </tr>
    </table>
  <%= f.submit "更新" %>
<% end %>
レイアウト2
    </table>
  <%= f.submit "登録" %>
<% end %>

1. 現在いるURLを参照し切り分ける方法

まず、_form.html.erbを作成し、request.path_infoで現在いるURLを参照し、そのURLによってレイアウトを切り分けます。
こんな感じです。

_form.html.erb
<%= 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 %>
new.html.erb
<%= form_for(@user, :url => {:action => 'create'} ) do |f| %>
  <%= render :partial => 'form', :locals => {:f => f} %>
<% end %>
edit.html.erb
<%= 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は以下の通りです。

_form.html.erb
<%= 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は以下の通りです。

new.html.erb
<%= form_for(@user, :url => {:action => 'create'} ) do |f| %>
  <%= render :partial => 'form', :locals => {:f => f} %>
<% end %>
edit.erb
<%= form_for(@pickup_client, :url => {:action => 'update'}) do |f| %>
  <%= render :partial => 'form', :locals => {:f => f, :edit_flag => true} %>
<% end %>

この切り分けのメリットとしては、各ページで使いたいレイアウト用にrenderの引数を定義すれば良いので、partialをいじる必要がなく、保守性が高いという点にあります。

83
79
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
83
79