LoginSignup
18
20

More than 5 years have passed since last update.

Railsで、同じFormで同じModelに対しての修正と登録を混在させる

Last updated at Posted at 2014-04-18

Railsで、同じFormで同じModelに対しての修正と登録を混在させる(一度のrequestでinsertとupdateを同時に行う)

既存データの一覧を表示し、まとめて編集できる表において、
行を追加して新規データも登録できるようなケースを想定します。

単純にsubmitすると次のエラーが発生します。

expected Hash (got Array) for param `samples'

これはParameterに対し、既存データはidをキーとしたハッシュで格納され、
新規データはidがないのでハッシュの配列で格納されるためです。

既存データ例:

"comments"=>{
  "1"=>{"id"=>"1", "title"=>"a", "content"=>"aa"}, 
  "2"=>{"id"=>"2", "title"=>"b", "content"=>"bb"}, 
  "3"=>{"id"=>"3", "title"=>"c", "content"=>"cc"}, 
  "4"=>{"id"=>"4", "title"=>"d", "content"=>"dd"}, 
  "5"=>{"id"=>"5", "title"=>"e", "content"=>"ee"}, 
  "6"=>{"id"=>"6", "title"=>"f", "content"=>"ff"}
}

新規データ例:

"comments"=>[
  {"id"=>"", "title"=>"a", "content"=>"aa"}, 
  {"id"=>"", "title"=>"b", "content"=>"bb"}, 
  {"id"=>"", "title"=>"c", "content"=>"cc"}, 
  {"id"=>"", "title"=>"d", "content"=>"dd"}, 
  {"id"=>"", "title"=>"e", "content"=>"ee"}, 
  {"id"=>"", "title"=>"f", "content"=>"ff"}
]

回避策として、新規データにダミーidを割り振り
受け取ったときにidの有無を見て新規作成と更新を切り分けます。

View例:

<table> 
  <tr>  
    <th>title</th>
    <th>content</th>
  </tr>
<% (0..5).each do |i| %>
  <% if @comments.present? && @comments[i].present? %>
    <!-- 既存データ -->
    <%= f.fields_for 'comments[]', @comments[i], index: @comments[i].id || "x#{i}" do |c| %>
      <tr id="comment<%=i+1%>">
        <%= c.hidden_field :id, :id => "id#{i+1}", :value => @comments[i].id %>       
        <td>
        <%= c.text_field :title, :id => "title#{i+1}", :value => @comments[i].title %>
        </td>
        <td>
        <%= c.text_field :content, :id => "content#{i+1}", :value => @comments[i].content %>
        </td>
      </tr>
    <% end %>
  <% else %>
    <!-- 新規データ -->
    <tr id="comment<%=i+1%>">
      <input id="id<%=i+1%>" name="user[comments][x<%=i+1%>][id]" type="hidden"/>   
      <td>
      <input id="title<%=i+1%>" name="user[comments][x<%=i+1%>][title]" />
      </td>
      <td>
      <input id="content<%=i+1%>" name="user[comments][x<%=i+1%>][content]" />        
      </td>
    </tr>
  <% end %>
<% end %>
</table>

Parameters例:

(次の例では2つが既存データでidのない2つが新規データ)

"comments"=>{
  "1"=>{"id"=>"1", "title"=>"a", "content"=>"aa"}, 
  "2"=>{"id"=>"2", "title"=>"b", "content"=>"bb"}, 
  "x3"=>{"id"=>"", "title"=>"c", "content"=>"cc"}, 
  "x4"=>{"id"=>"", "title"=>"d", "content"=>"dd"}, 
}

Controller側で、idの中身を見て更新と新規登録を切り分けます。

--

動作確認用サンプルソースはGitHubにアップしています。

18
20
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
18
20