LoginSignup
140
162

More than 5 years have passed since last update.

【Rails】複数のレコードを作成する。modelの関係性によって異なるform_for / fields_forの使い方

Posted at

一つのフォームから複数のmodelにデータを送りたい場合に使用するのが、form_for / fields_forです。ただし、その複数存在するmodel間の関係性によって微妙に使い方が違うのをご存知ですか??今回は、その違いをまとめてみました。

親と子の要素を一度に作成したい場合

userとそのuserの書いたbook(つまり、user_idを持つbook)をまとめて作成したい場合
  • model
user.rb
has_many :books: 

accepts_nested_attributes_for :books: 
book.rb
belongs_to :user
  • controller
users_controller.rb
class UsersContoller < AppricationController
    def new
    @user = User.new
    @user.books.build
    # controllerのポイント
    # @user.books.build ←これで一括保存の準備は完了
    end

    def create
    user = User.new(user_params)
    user.save
    # 親要素を保存かけてあげることで自動で子要素も保存されます!
    end

    private 

        def user_params
            params.require(:user).permit(:name, books_attributes: [:title, published_at])
            # これは独特な書き方ですが、このように子要素のstrong parameterを書くことで、自動で子要素に親要素のidもふられます。この場合だと、bookテーブルにあるuser_idにもきちんとこの時作成される親要素のidがふられます。
        end
end
  • view
users/new.html.erb
<%= form_for :user do |f| %>
    <%= f.text_field :name %>

    <%= f.fields_for :books do |b| %>
        <%= b.text_field :title %>
        <%= b.text_field :published_at %>

    <%= f.submit %>
<% end %>

model間の関係は親子関係など特に無いが、一つのフォームから複数のmodelにむけてデータを送りたい場合

userテーブルとcorporationテーブルに一つのフォームからデータを送りたい場合
  • controller
users_controller.rb
class UsersController < ApplicationController
    def new
        @user = User.new
        @corporation = Corporation.new
        # それぞれ.newをする
    end

    def create
        user = User.new(user_params)
        user.save

        corporation = Corporation.new(corporation_params)
        corporation.save
        # それぞれcreate処理を行う
    end

    private

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

        def corporation_params
            params.require(:corporation).permit(:name)
        end
end
users/new.html.erb
<%= form_for @user, url: new_user_params do |f| %>
    <%= f.text_field :name %>

    <%= fields_for @corporation, new_corporation_params do |c| %>
        <%= c.text_field :name %>

    <%= f.submit %>
<% end %>

このようにして、model間の関係がないものも一つのフォームから送ることができます。
ちなみに、この場合パラメーターは以下のようになるので、それぞれstrog parameterでpermitしてあげてcreateすれば保存完了です。

{ "user" => { "name" => "userテスト"}, "corporation" => { "name" => "corporationテスト"}
140
162
1

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
140
162