質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

2449閲覧

rails6を使ってテーブルに複数のレコードを一括保存したい

hieee

総合スコア1

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2021/05/13 01:34

前提・実現したいこと

rails6を使ってテーブルにレコードを一括保存したいです。

発生している問題・エラーメッセージ

エラーメッセージは出ませんがbinding.pryをかけるとuser_idがnilになります。

該当のソースコード

ruby

1class MenusController < ApplicationController 2 def index 3 @menus = Menu.all.order(created_at: :desc).includes(:user) 4 end 5 6 def new 7 @form = Form::MenuCollection.new 8 end 9 10 def create 11 @form = Form::MenuCollection.new(menu_collection_params) 12 if @form.save 13 redirect_to root_path 14 else 15 render :new 16 end 17 end 18 19 private 20 21 def menu_collection_params 22 params.require(:form_menu_collection).permit(menus_attributes: [:training_date, :part, :training, :weight, :rep,:memo]).merge(user_id: current_user.id) 23 end 24 25 26end

ruby

1class Form::Base 2 include ActiveModel::Model 3 include ActiveModel::Callbacks 4 include ActiveModel::Validations 5 include ActiveModel::Validations::Callbacks 6end

ruby

1class Form::MenuCollection < Form::Base 2 FORM_COUNT = 3 3 attr_accessor :menus,:user_id 4 5 def initialize(attributes = {}) 6 super attributes 7 self.menus = FORM_COUNT.times.map { Menu.new() } unless self.menus.present? 8 end 9 10 11 def menus_attributes=(attributes) 12 self.menus = attributes.map{ |_, v| Menu.new(v) } 13 end 14 15 16 17 def save 18 19 Menu.transaction do 20 self.menus.map(&:save!) 21 end 22 return true 23 rescue => e 24 return false 25 end 26end

ruby

1class Menu < ApplicationRecord 2 belongs_to :user 3 validates :training_date, presence: true 4 validates :part, presence: true 5 validates :training, presence: true 6 validates :rep, presence: true 7end 8

ruby

1class User < ApplicationRecord 2 # Include default devise modules. Others available are: 3 # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable 4 devise :database_authenticatable, :registerable, 5 :recoverable, :rememberable, :validatable 6 has_many :menus 7 accepts_nested_attributes_for :menus 8 9 validates :nickname, presence: true 10 11end
<div class="new-training"> <%= form_with model: @form,url: menus_path, method: :post,local: true do |f|%> <%= f.fields_for :menus do |i|%> <div class="menu-forms"> <div class="taraining-date"> <%= i.label :training_date,"日付",id:"date" %><br /> <%= i.datetime_field :training_date %> </div> <div class="menu-form"> <%= i.label :training, "種目" %><br /> <%= i.text_field :training,id:"menu_training" %> </div> <div class="menu-form"> <%= i.label :weight, "重量" %><br /> <%= i.number_field :weight,id:"menu_weight" %>kg </div> <div class="menu-form"> <%= i.label :rep, "rep" %><br /> <%= i.number_field :rep,id:"menu_rep" %>回 </div> <div class="hidden-content"> <%= i.hidden_field :part ,:value => "胸", id:"menu_part" %> </div> </div> <% end %> <div class="menu-low"> <div class="memo"> <%= f.label :memo, "MEMO" %><br /> <%= f.text_area :memo,id:"menu_memo" %> </div> <div class="menu-submit"> <button type="submit" class="btn">記録する</button> </div> </div> <% end %> </div>

試したこと

外部サイトを参考にし、実装しています。
attr_accesorにuser_idを記述して、user.rbにaccepts_nested_attributes_for :menusの記述をしました。
また、binding.pryをcreateアクションで行うと
[1] pry(#<MenusController>)> @form
=> #<Form::MenuCollection:0x00007f872026ccb8
@menus=
[<Menu:0x00007f871ca98198
id: nil,
training_date: Wed, 12 May 2021,
part: "胸",
training: "a",
weight: 1,
rep: 1,
memo: nil,
user_id: nil,
created_at: nil,
updated_at: nil>,
<Menu:0x00007f87278ac298
id: nil,
training_date: Wed, 12 May 2021,
part: "胸",
training: "b",
weight: 2,
rep: 2,
memo: nil,
user_id: nil,
created_at: nil,
updated_at: nil>,
<Menu:0x00007f87278b7800
id: nil,
training_date: Wed, 12 May 2021,
part: "胸",
training: "c",
weight: 3,
rep: 3,
memo: nil,
user_id: nil,
created_at: nil,
updated_at: nil>],
@user_id=1>
と表示され、user_idのみ"nil"となってしまいます。

補足情報(FW/ツールのバージョンなど)

rails 6.0.0

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

MenusControllermenu_collection_params がおかしいと思います。
順を追って確認していきましょう。
まず、controller が受け取る生の params は以下のような構造になっています。

rb

1# params 2{ 3 'form_menu_collection' => { 4 'menus_attributes' => { 5 '0' => { 6 'training_date' => '...', 'part' => '...', (中略), 'memo' => '...' 7 }, 8 '1' => { 9 'training_date' => '...', 'part' => '...', (中略), 'memo' => '...' 10 } 11 } 12 } 13}

これを requirepermit で処理すると以下のようなハッシュになります。

rb

1# params.require(...).permit(...) 2{ 3 'menus_attributes' => { 4 '0' => { 5 'training_date' => '...', 'part' => '...', (中略), 'memo' => '...' 6 }, 7 '1' => { 8 'training_date' => '...', 'part' => '...', (中略), 'memo' => '...' 9 } 10 } 11}

このハッシュに対して .merge(user_id: ...) を行っているので、最終的なハッシュは

# params.require(...).permit(...).merge(...) { 'menus_attributes' => { '0' => { 'training_date' => '...', 'part' => '...', (中略), 'memo' => '...' }, '1' => { 'training_date' => '...', 'part' => '...', (中略), 'memo' => '...' } }, 'user_id' => 123 # ← ここにマージされちゃう }

となります。

でも、本来 user_id は以下のように追加する必要があります。

# 本当は↓みたいな形にしないといけない { 'menus_attributes' => { '0' => { 'training_date' => '...', 'part' => '...', (中略), 'memo' => '...', 'user_id' => 123 }, '1' => { 'training_date' => '...', 'part' => '...', (中略), 'memo' => '...', 'user_id' => 123 } } }

なので、上記のようなハッシュになるよう、 MenusController#menu_collection_params を修正してあげれば良いと思います。

投稿2021/05/13 08:44

shinoharat

総合スコア1676

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hieee

2021/05/13 08:57

mergeにこだわりすぎていました、、 無事解決できました!!!!!ありがとうございます!!!!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問