LoginSignup
249
247

More than 5 years have passed since last update.

Railsで1つのフォームで複数のモデルを登録・更新させる

Last updated at Posted at 2017-03-09

アソシエーションとかで紐付いている複数モデルを、1つのフォームで入力させて登録・更新する方法について調べた。

Model

companyモデルに会社の経理情報を持ったcompany_financialモデルが1対1でリンクしている。
ポイントとしては、company更新時に付随するcompany_financialを、accepts_nested_attributes_forに指定するところ。

company.rb
class Company < ActiveRecord::Base
  has_one :company_financial
  accepts_nested_attributes_for :company_financial
end
company_financial.rb
class CompanyFinancial < ActiveRecord::Base
  belongs_to :company
end

Controller

ポイントは以下の二つ。
- strong parameterに、company_financial_attributesを追加してあげる。(更新時のためにidもパラメータに含めておく)
- 付随するアソシエーションも同時に登録する場合はbuildであらかじめ作成しておくこと。(has_oneではbuildが使えないのでbuild_~~を使用します)

company_financial.rb
class CompaniesController < ApplicationController
  before_action :find_company, only: [:show, :edit, :update, :destroy]

  def new
    @company = Company.new
    @company.build_company_financial
  end

  def edit
  end

  def create
    @company = Company.new(company_params)
    @company.save!
    redirect_to company_path(@company)
  rescue
    render action: 'new'
  end

  def update
    @company.update!(company_params)
    redirect_to company_path(@company)
  rescue
    render action: 'edit'
  end

  private

    def find_company
      @company = Company.find(params[:id])
    end

    def company_params
      params.require(:company).permit(:name, company_financial_attributes: [:id, :bank_info])
    end

end

View

fields_forでネストすることで、アソシエーションのフィールドを設置できる。

companies/new.html.slim
= form_for @company, url: companies_path do |f|
  .form-group
    = f.label :name
    = f.text_field :name
  = form.fields_for :company_financial: do |fin|
    .form-group
      = fin.label :bank_info
      = fin.text_field :bank_info

Model間の関係はないが、1つのフォームで複数モデルの登録をしたい場合

strong parameterを分けて、それぞれでsaveすればOK.

company_financial.rb
class CompaniesController < ApplicationController
  before_action :find_company, only: [:show, :edit, :update, :destroy]

  def new
    @company = Company.new
    @user = User.new
  end

  def create
    @company = Company.new(company_params)
    @company.save!
    @user = User.new(user_params)
    @user.save!
    redirect_to company_path(@company)
  rescue
    render action: 'new'
  end

  private

    def company_params
      params.require(:company).permit(:name)
    end

    def user_params
      params.require(:user).permit(:name)
    end
end

View

companies/new.html.slim
= form_for @company, url: companies_path do |f|
  .form-group
    = f.label :name
    = f.text_field :name
  = form.fields_for @user do |user|
    .form-group
      = user.label :name
      = user.text_field :name
249
247
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
249
247