【Rails】1つのフォームタグで紐付いたテーブルの項目も登録したい場合
例えば「企業(company)」テーブルと「事業所(office)」テーブルがあるとします。
企業と事務所の関係は、企業が複数の事業所を持っているということで、1対多の関係です。
モデルの紐付けと設定
親のcompanyに「accepts_nested_attributes_for :offices」の1文を記載する。
【models/company.rb】
class Company < ApplicationRecord has_many :offices, inverse_of: :company accepts_nested_attributes_for :offices end
【models/office.rb】
class Office < ApplicationRecord belongs_to :company, inverse_of: :offices end
inverse_ofはcompanyもofficeも新規で作成する場合、もとにするcompanyのidが見つからないというエラーを起こすので、それを防ぐために記載する
@companyの定義と関連テーブルのbuild
@companyを定義し、紐づく@officesをbuildします
【controllers/company_controller.rb】
class CompaniesController < ApplicationController def new @company = Company.new @office = @company.offices.build end end
追加でparamsの受け取りも定義してやります。
class CompaniesController < ApplicationController def new @company = Company.new @office = @company.offices.build end private def company_params params.require(:company).permit( :name, :url, offices_attributes: [:id, :company_id, :name, :postal, :prefecture, :address, :building, :tel, :fax, :remark] ) end end
最後にviewのフォームを設定
@companyの項目はいつも通りに、buildしたofficeの項目について「fields_for」で入力項目を出します。
※controllerでbuildしないと入力項目が表示されません
【views/companies/_form.html.erb】
<%= form_with(model: @company) do |form| %> <table> <tr> <th rowspan="3"><%= form.label f(Company, :name) %></th> <td class="sub"><%=f Company, :name %></td> <td><%= form.text_field :name %></td> </tr> <tr> <th><%= form.label f(Company, :url) %></th> <td colspan="2"><%= form.text_field :url %></td> </tr> <%= form.fields_for :offices do |office| %> <tr> <th><%= office.label :postal %></th> <td colspan="2"> <%= office.text_field :postal %> </td> </tr> <tr> <th><%= office.label :prefecture %></th> <td colspan="2"> <%= office.select :prefecture, PrefectureList %> </td> </tr> <tr> <th><%= office.label :address %></th> <td colspan="2"> <%= office.text_field :address %> </td> </tr> <tr> <th><%= office.label :building %></th> <td colspan="2"> <%= office.text_field :building %> </td> </tr> <tr> <th><%= office.label :tel %></th> <td colspan="2"> <%= office.text_field :tel %> </td> </tr> <tr> <th><%= office.label :fax %></th> <td colspan="2"> <%= office.text_field :fax %> </td> </tr> <tr> <th><%= office.label :remark %></th> <td colspan="2"> <%= office.text_area :remark %> </td> </tr> <% end %> </table> <%= form.submit %> <% end %>
こんな感じでフォームを分けなくても一気に登録することができます。
筆者オススメ技術書
リンク