前提・実現したいこと
プログラミング初学者です。よろしくお願いします!
RailsとjQueryを使った実装にて、動的フォーム(jQuery)で追加したフォームを、Railsを通してデータベース(MySQL)に全て保存したいです。
(料理の味付け法を共有するサイトを作っています。ややこしいのでレシピサイトのようなものと同じと考えてくださって大丈夫です)
発生している問題・エラーメッセージ
エラー文はconsole、ターミナルともに起こっていません。
データベースへの保存のみ出来ていません。
該当のソースコード
コントローラー
tastes_controller
ruby
1class TastesController < ApplicationController 2 def index 3 @taste = Taste.all 4 end 5 6 def new 7 @taste = Taste.new 8 # @taste.build_seasoning 9 # @taste.seasonings.build 10 #親モデルとアソシエーションを組んでいる子モデルのインスタンスを生成 11 end 12 13 def create 14 # @taste = Taste.new(taste_params) 15 # if @taste.save 16 # redirect_to root_path 17 @taste = Taste.create(taste_params) 18 if @taste.save 19 redirect_to root_path 20 else 21 render :new 22 end 23 end 24 25 private 26 27 def taste_params 28 params.require(:taste).permit(:title, :example, :image, :genre_id, seasoning_attributes: [:seasoning_name, :quantity]).merge(user_id: current_user.id) 29 end 30end
モデル
taste.rb
Ruby
1class Taste < ApplicationRecord 2 has_one_attached :image 3 belongs_to :user 4 has_one :seasoning 5 accepts_nested_attributes_for :seasoning, allow_destroy: true 6 extend ActiveHash::Associations::ActiveRecordExtensions 7 belongs_to :genre 8 9 with_options presence: true do 10 validates :image 11 validates :title 12 validates :example 13 validates :genre_id, numericality: { other_than: 1 } 14 validates :user_id 15 end 16 17end
モデル
seasoning.rb
Ruby
1class Seasoning < ApplicationRecord 2 belongs_to :taste, optional: true 3end
ビュー
new.html.erb
Ruby
1<%= render "/shared/header" %> 2 3<div class="inner-contact"> 4 <div class="contact-form"> 5 <%= form_with(model: @taste, local: true) do |f| %> 6 <%#エラーメッセージの表示 %> 7 <%= render "shared/error_messages", model: f.object, class: "error-messages" %> 8 <div class= "form"> 9 <div class="form_left"> 10 <div class="weight-darkcyan-text"> 11 テイスト名 12 </div> 13 <%= f.text_area :title, class:"taste_title", placeholder:"例) 濃厚ケチャップ味" %> 14 <div class="weight-darkcyan-text"> 15 使用例の料理写真 16 </div> 17 <%= f.file_field :image, class:"taste_image" %> 18 <div class="weight-darkcyan-text"> 19 おすすめジャンル 20 </div> 21 <%= f.collection_select(:genre_id, Genre.all, :id, :name, {}, {class:"select-box", id:"create-hour"}) %> 22 <div class="weight-darkcyan-text"> 23 作った料理 24 </div> 25 <%= f.text_field :example, class:"how_to_cooks", placeholder:"例) 唐揚げ" %> 26 </div> 27 <div class="form_right"> 28 <%= f.fields_for :seasoning, @taste.build_seasoning do |seasoning| %> 29 <div class="seasoning_field" id="seasoning_field[0]"> 30 <%= seasoning.text_field :seasoning_name, class:"seasoning_name", placeholder:"例) 醤油", name:"seasoning_name[0]", id:"seasoning_name[0]" %> 31 <%= seasoning.text_field :quantity, class:"quantity", placeholder:"例) 大さじ2", name:"quantity[0]",id:"quantity[0]" %> 32 </div> 33 <%= f.button '+', id: "add_btn", type: "button" %> 34 <% end %> 35 </div> 36 </div> 37 <%= f.submit "submit", class:"form-btn semibold" %> 38 <% end %> 39 </div> 40</div> 41 42<%= render "/shared/footer"%>
JS
taste.js
jQuery
1 $(function(){ 2 // フォームカウント 3 var frm_cnt =0; 4 // クローンする 5 $('#add_btn').on('click', function(){ 6 var original = $('#seasoning_field\[' + frm_cnt + '\]'); 7 var originCnt = frm_cnt; 8 9 frm_cnt++; 10 11 original 12 .clone() 13 .appendTo(original) 14 .attr('id', 'seasoning_field[' + frm_cnt + ']') 15 .end() 16 .find('input, text_field').each(function(idx, obj) { 17 $(obj).attr({ 18 id: $(obj).attr('id').replace(/[[0-9]]+$/, '[' + frm_cnt + ']'), 19 name: $(obj).attr('name').replace(/[[0-9]]+$/, '[' + frm_cnt + ']') 20 }); 21 $(obj).val(''); 22 }); 23 }); 24}); 25
試したこと
- Rubyでform内の値をデータベース保存する方法はこちらを参照しました。
https://qiita.com/nakasato_minami/items/5015319292c9f8a93f34
- レシピサイトの作成で同様に動的フォームの作成、保存をしている方も参照させていただきました。
https://teratail.com/questions/264073
いろいろいじってた結果、こちらの記述を変更した時のみデータベースへの保存が可能になりました。(レコード一つのみでしたが,,,)
Ruby
1<%= f.fields_for :seasoning, @taste.build_seasoning do |seasoning| %> 2 <div class="seasoning_field" id="seasoning_field[0]"> 3 <%= seasoning.text_field :seasoning_name, class:"seasoning_name", placeholder:"例) 醤油", name:"seasoning_name[0]", id:"seasoning_name[0]" %> 4 <%= seasoning.text_field :quantity, class:"quantity", placeholder:"例) 大さじ2", name:"quantity[0]",id:"quantity[0]" %> 5 </div> 6 <%= f.button '+', id: "add_btn", type: "button" %> 7 <% end %>
↑こちらのname属性の、**name:"seasoning_name[0]"とname:"quantity[0]"**を削除した場合、最下層に追加した値のみ、データベースへ保存されました。
ちなみコンソール上ではformの追加はされてるように見受けられます。
https://gyazo.com/61550f3891bd44baf2c3d16ce9b6254a
補足情報(FW/ツールのバージョンなど)
Ruby on Rails 6
DBはMySQLを使用しています。
自己分析
binding.pryでtaste_paramsを確認。
taste_params[:quantity]で確認するとnilに、、
seasoningsテーブルへの保存処理に問題あり?
- コントローラーとモデルの確認
- おあとjQueryの記述方が正しいか、学習も兼ねて復習。(特にname属性について)
13: def create => 14: binding.pry 15: @taste = Taste.create(taste_params) 16: if @taste.save 17: redirect_to root_path 18: else 19: render :new 20: end 21: end [1] pry(#<TastesController>)> taste_params[:quantity] => nil [2] pry(#<TastesController>)> taste_params[:title] => "濃厚ケチャップ味"
自己分析追記
テーブル設計の問題かと思い、アソシエーションの確認。
初期では1対1で考えていたが、レコードを複数保存すると考えると1対多では?と思い、テーブル、アソシエーションを修正。状況変わらず。
そもそもname属性がなくてもformの追加ができている→nameではないもので値を取得している?
怪しいのはid?
あなたの回答
tips
プレビュー