Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

アソシエーションとかで紐付いている複数モデルを、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
tmzkysk
普段は仕事でruby書いてる人です。 バックエンド寄りです。
maplesystems
エンジニアの未来を考えるサービスを開発・運営するスタートアップ
http://www.maplesystems.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした