フォームオブジェクトで fields_for を使う:newの場合の続き。
edit.html.erbの準備
new.html.erbと共通部分を _form.html.erb へ抜き出す。
new.html.erbは以下のとおり。なお、最後の #editアクションへのリンクの中のidは適当に決めている(今回はidを使わないため)。また、form_data をパーシャルのlocals属性を使って、_form.html.erbへ渡している。
<%= bootstrap_form_for(@book_list, :url => {controller: :input_forms, action: :create}) do | form_data |-%> <%= render partial: 'form', locals: {form_data: form_data} %> <% end -%> <hr> <%= link_to 'Edit', edit_input_form_path(1) -%>
edit.html.erb は以下のとおり。メソッドとして patch を指定する必要がある。
<%= bootstrap_form_for(@book_list, url: {controller: :input_forms, action: :update}, method: :patch) do | form_data |-%> <%= render partial: 'form', locals: {form_data: form_data} %> <% end -%>
_form.html.erb は以下のとおり。
<%= form_data.fields_for :books do | field_data | -%> <%= field_data.text_field :title %> <%= field_data.text_field :author %> <%= field_data.number_field :price %> <%= field_data.text_field :isbn %> <% end -%> <%= form_data.submit %>
edit.html.erbの方では、隠しフィールドとして、Bookオブジェクトのidを送る inputタグが生成される。
コントローラーの変更
InputFormsControllerに#edit アクション、 #update アクションを追加し、Strong Parameter用のメソッドに :id を追加する。
def edit @book_list = BookInputForm.new @book_list.load #新たにインスタントメソッドを用意する end def update #createアクションと同じだが、内部でupdateを読んでいるのでsaveしない。 @book_list = BookInputForm.new(book_input_params) redirect_to books_path end private def book_input_params # :id を新たに付け加える params.require(:book_input_form).permit(books_attributes: [:id, :title, :author, :price, :isbn]) end
フォームオブジェクトの変更
BookInputFormに、既に格納済みのBookオブジェクトを読み込む loadメソッドを追加する。
def load @books = Book.all.to_a end
また、#updateアクションにて、#createと同じ書き方をできるようにbooks_attributesを変更する。
def books_attributes=(attributes) @books ||= [] attributes.each do | i, book_params| if book_params.key?(:id) # :idキーが追加されているならば、更新である book = Book.find(book_params[:id]) book.update(book_params) unless book.blank? else # :idキーがなければ新規作成 @books.push(Book.new(book_params)) end end end
これで、既に保存済みのBookオブジェクトもまとめて編集できる。