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

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

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

Haml(HTML abstraction markup language)は、HTML/XHTMLを効率的に記述するためのマークアップ言語および記法です。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

Ruby on Rails

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

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

Q&A

解決済

1回答

3545閲覧

1つのフォームで親レコードと複数の子レコードを保存したいが、accepts_nested_attributes_forが機能せずキー名が正しく表示されない

shota-imoto

総合スコア37

Haml

Haml(HTML abstraction markup language)は、HTML/XHTMLを効率的に記述するためのマークアップ言語および記法です。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Model

MVCモデルの一部であるModelはアプリケーションで扱うデータとその動作を管理するために扱います。

Ruby on Rails

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

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

0グッド

1クリップ

投稿2020/05/10 09:49

編集2020/05/17 21:49

前提・実現したいこと

一つのフォームでアソシエイトが組まれた2つのモデルを生成したい。
タイトルの通り、accepts_nested_attributes_forが正しく機能してくれません。
そこさえ解決すればあとは問題なく実装できると踏んでいます。

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

以下のページのように実装。
https://qiita.com/ftyabu/items/cae912b211e985d74d58

親モデルにあたるsongはDBに保存されるが、子モデルであるkeyは保存されない

該当のソースコード

Songモデル(親)

rails

1class Song < ApplicationRecord 2 has_many :keys, dependent: :destroy 3 accepts_nested_attributes_for :keys 4 belongs_to :user 5end

Keyモデル(子)

rails

1class Key < ApplicationRecord 2 belongs_to :song 3end

songコントローラのnewおよびcreateアクション

rails

1def new 2 @song = Song.new 3 @song.keys.build 4end 5 6def create 7 @song = Song.new(song_params) 8 9 respond_to do |format| 10 if @song.save 11 format.html { redirect_to @song, notice: 'Song was successfully created.' } 12 format.json { render :show, status: :created, location: @song } 13 else 14 format.html { render :new } 15 format.json { render json: @song.errors, status: :unprocessable_entity } 16 end 17 end 18end

songコントローラのストロングパラメータ

rails

1def song_params 2 params.permit(:title, :jam, :standard, :beginner, keys_attributes: [:name, :instrumental, :male, :female]).merge(user_id: current_user.id) 3end

viewファイル

haml

1.contents__title 2=form_with url: songs_path, class: "contents__form", method: :post, local: true do |f| 3 .form--title 4 = f.label "タイトル" do 5 = f.text_field :title 6 .form__class 7 =f.label :jam, class: "class--element" do 8 = f.check_box :jam, checked_value: "1", unchecked_value: "0" 9 ジャムセッション向け曲 10 =f.label :standard, class: "class--element" do 11 = f.check_box :standard, checked_value: "1", unchecked_value: "0" 12 スタンダード曲 13 =f.label :beginner, class: "class--element" do 14 = f.check_box :beginner, checked_value: "1", unchecked_value: "0" 15 初心者向け曲 16 .form__key 17 =f.fields_for :keys do |key_f| 18 .chord-menu 19 .chord-menu__key 20// 中略 21 = f.submit "登録" 22 23

試したこと

  • accepts_nested_attributes_for :keysが機能しているか。
28: def create 29: @song = Song.new(song_params) 30: binding.pry => 31: respond_to do |format| 32: # 省略 39: end 40: end [1] pry(#<SongsController>)> params => <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"pOCRwVjfMP3Ku97oMWzWcZbKmULQAGyik+dEB/bVPpJPm0js+7rPkynSc1Ad8BvbH2y/pfbQLKLgovVMimnGfg==", "title"=>"why did you wonder", "jam"=>"0", "standard"=>"1", "beginner"=>"1", "keys"=>{"name"=>"key of G", "instrumental"=>"0", "male"=>"1", "female"=>"0"}, "commit"=>"登録", "controller"=>"songs", "action"=>"create"} permitted: false>

ネストはされているが、キー名がkeys_attributesではなく、keys

  • ストロングパラメータ中のpermitの中の値をkeysに変更

「name(keysにネストされているキー名)はインスタンスのキーに存在しない」というニュアンスのエラーが発生しました。
イメージ説明

  • 関係はなさそうだが、optional: trueやinverse_ofなどの記述も試す

リスト エラーの原因がid違反でもvalidateでもないので関連はなさそうですが、以下のサイトの内容を試しました
0. inverse_of
https://qiita.com/Hiroyuki_OSAKI/items/bfb20c481e6c4970f415

0. optional: true
https://qiita.com/a-itabashi/items/6e0d4793996d887fd191

特に変化なし。キー名は相変わらずkeysのままでkeys_attributesにはなっていませんでした。

  • accepts_nested_attributes_forを使用せずに実装する方法を模索。

accepts_nested_attributes_forを使わず、複数の子レコードを保存する
前提として、accepts_nested_attributes_forを使用しなくてもキー名が○○_attributesとなっていたので、これは参考になりませんでした。

  • hamlの記述を確認する

記述に誤りはありませんでした
https://qiita.com/onigirimantarou/items/1281093334b38a9cd67c
fields_for以外の方法は今の所試していません

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

− ruby 2.5.1p57

  • rails (5.2.4.2)
  • haml (5.1.2)
  • haml-rails (2.0.1)
  • jbuilder (2.10.0)
  • mysql2 (0.5.3)
  • 他にjqueryとscssを併用しています。

これからfields_for以外の方法を試すつもりです。
かれこれ12時間ほど詰まっているので教えていただけると幸いです。

よろしくお願いいたします。

追記 試したこと

フォームで送るキー名を工夫

別画面で実装した際にも同様にaccepts_nested_attributes_forコマンドが機能しませんでした。
いっそ、フォームの方でごまかしせないか?と考えviewファイルを変更しました。field_forで送るキー名を変更してみました。

※別画面に実装しようとした際には、違うモデルを使っていますが混乱を避けるため、この質問で用いられるモデルに書き換えて、結果を表記します

viewファイル

haml

1//略 2.form__key 3 =f.fields_for :keys_attributes do |key_f| 4//略

ストロングパラメータsong_paramsの出力は以下の通りです。

<ActionController::Parameters {"title"=>"why did you wonder", "jam"=>"0", "standard"=>"1", "beginner"=>"1", "keys_attributes"=><ActionController::Parameters {"name"=>"key of G", "instrumental"=>"0", "male"=>"1", "female"=>"0"} permitted: true>} permitted: false>

すると別のエラーメッセージが表示されました。
エラー画像
@tuning_allの行が

@song = Song.new(song_params)

にあたります。変数の型とは違う型を代入している際にでるエラーのようです。
accepts_nested_attributes_forは表面的に表示を変える以上の働きをしているのかな?と考えました。

フォームオブジェクトという初心者にはハードル高そうなものを使えば、accepts_nested~を使わなくても実装できるようなので、一度チャレンジしてみます。

accepts~で同じエラーが発生している記事を発見

Rails fields_for と accepts_nested_attributes_for を使うときの注意点
それって書き方変えただけじゃないの?というような内容ですが、わらにもすがる思いで真似してみましたが、結果変わらず。
内容を要約すると、

  • 子要素のモデルを作って送れているか?
  • accepts~のあとに記述したものと、field_forでつけたキー名が一致しているか?

子要素のモデルに関してはfield_forのところで定義されていたので、私が親コントローラのnewアクションのところで記述していたものを同じように書いてためしました。念の為。

追記 シンプルな疑問

accepts〜の記述を受け付けないという事象は(原因は何にせよ、一般的に)そもそも発生し得ることなのでしょうか?
例えば○○Gemをbundle installしていないと機能しない、versionX.Xでは機能しない、など一定の条件下では反応しないことがありうるのでしょうか。
あり得る場合、エラーは発生するのでしょうか?それとも今起きているようにエラーは発生せず無視されるものなのでしょうか。

解決に直接至らなくてもそのあたりの切り分けがしたいので、情報があれば教えていただきたいと思っています。

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

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

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

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

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

winterboum

2020/05/23 17:40

読めない(推理できない)んです。 codeが断片的すぎる。 肝心の keysのところが省略されている 実際のmodelと違う名前の様だ なので、エラーが起きたのが載っているcodeの時なのかどうかも確信できなくなっている。 質問書きなおしてください。 何をしたか、は残して欲しいですが、controller、view、log/developpment.logのStarted POST から次のStartedまで を。 実際のプログラムと名前を変えるなら全ての資料を確実に修正してください。 @tuning_allの行が@song = Song.new(song_params)ですと言われても混乱するだけです。
guest

回答1

0

自己解決

まっさらなところから再度書き出して、再度実行するとうまくいきました。
accepts_for〜文によってparamsに[子要素の複数形]_attributesというキーが正常に追加されました。

viewファイルが怪しいのですが、正直詳細は不明です。

うまく行ったコードとの差異としては

Haml

1 2// before 3=form_with url: songs_path, class: "contents__form", method: :post, local: true do |f| 4 5// after 6=form_with model: @song, url: songs_path, class: "contents__form", method: :post, local: true do |f| 7

のように親レコードのモデルを明記したところです。

疑っていたfields_forの記述の方は

Haml

1f.fields_for :keys do |key_f|

と初期状態のままです。

同じ現象に陥った場合は試してみてください。

投稿2020/06/07 02:14

shota-imoto

総合スコア37

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問