フォームオブジェクトで 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オブジェクトもまとめて編集できる。