前提・実現したいこと
一つのフォームでアソシエイトが組まれた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では機能しない、など一定の条件下では反応しないことがありうるのでしょうか。
あり得る場合、エラーは発生するのでしょうか?それとも今起きているようにエラーは発生せず無視されるものなのでしょうか。
解決に直接至らなくてもそのあたりの切り分けがしたいので、情報があれば教えていただきたいと思っています。
回答1件
あなたの回答
tips
プレビュー