Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

一つのform_forで複数のテーブルに保存!!

More than 3 years have passed since last update.

概要

  • スキルアップのため、レシピ投稿サイトを作っていました(cookpadのようなもの)。
  • 一つのレシピにつき、複数の写真を投稿できるようにしたかった。
  • 以下の記事を参考に、form_for + fields_forで、recipeレコードが保存されると、それに関連したimageレコードも保存されるようにした。

複数のレコードを作成する。modelの関係性によって異なるform_for / fields_forの使い方
Rails 複数の子レコードの作成・更新を自在に扱う (accepts_nested_attributes_for)
Railsで階層化された複数モデルに対応するフォームの作り方

上記サイトのコピーで、書いたコード

  • コントローラー
recipes_controller.rb
class RecipesController < ApplicationController
  def new
    @recipe = Recipe.new
    @recipe.images.build
  end

  def create
    recipe = current_user.recipes.new(recipe_params)
    recipe.save
    redirect_to root_path
  end

  private

  def recipe_params
    params.require(:recipe).permit(:name, images_attributes: [:image])
  end

end
  • ビュー
new.html.erb
<%= form_for @recipe do |f|  %>
  <%= f.text_field :name %>
  <%= f.fields_for :images do |i| %>
    <%= i.file_field :image %>
  <% end %>
  <%= f.submit "Save",name:"commit" %>
<% end %>

  • imageモデル
image.rb
class Image < ApplicationRecord
  belongs_to :recipe
end
  • recipeモデル
recipe.rb
class Recipe < ApplicationRecord
  belongs_to :user
  has_many :images
  accepts_nested_attributes_for :images
end

しかし、これだと保存されない!!

  • 結論から言うと、imageモデルの記述を、belongs_to :recipe,optional: trueにすると無事に保存されました!!
  • なぜ、optional: trueがないと、ダメかと言うと、rails5から、belongs_toに対して、required:trueがデフォルトで設定されているからみたいです。

required:trueとは

  • (私の理解が正しければ)値がnilだと保存されないよ!というものです。
  • つまり、imageモデルにはbelongs_to :recipeしか書いてなくとも、実際はbelongs_to :recipe,required:trueとなっているということです。

rails5はデフォルトでは、外部キー(hoge_id)のnilは許させない!!

  • DBに保存されるまでは、idはnilなので、つまり、imageモデルでの時点では、recipe_id(imageレコードの外部キー)はnilなので、 required:trueのバリデーションに引っかかり、保存されなかったということみたいです!!

optional: trueはrequired:trueを無効化する!!

  • これで無事に保存されました!!
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