form_forで複数のレコードを一括登録する

やりたいこと。

 

 

logsテーブル(カラムは 名前、タンパク質、脂質、炭水化物、記録時間)を一つのボタンで一括登録する。

 

お米と牛肉など別々のlogとして登録したい場合に、一括で登録できる方が利便性が高いと考えました。

 

.form.collection-item
 = form_for [@log] do |f|
  .main_content
   .card.text_form.log_new_form
   %p 食品名
   = f.text_field :name, index: 0, placeholder: ' food'
   %p タンパク質
   = f.text_field :protein, index: 0, placeholder: ' protein(g)'
   %p 脂質
   = f.text_field :fat, index: 0, placeholder: ' fat(g)'
   %p 炭水化物
   = f.text_field :carbohydrate ,index: 0, placeholder: ' carbohydrate(g)'
   .datetime
    = f.datetime_select :start_time, index: 0, class:"datepicker"

 

form_forのfieldにインデックスナンバー(0..10等)を入力し複数の入力フォームを作成。

indexを付与することでname値を区別して飛ばすことができます。(name値が同じだと、複数のlogのうち、最後のlogのみ保存されることになります。)

 

log (index=0)の卵

log(index=1)のお米

を入力し、binding.pryで止めてみる

 

[1] pry(#<LogsController>)> params[:log]

=> <ActionController::Parameters {"0"=>{"name"=>"", "protein"=>"1", "fat"=>"1", "carbohydrate"=>"2", "start_time(1i)"=>"2019", "start_time(2i)"=>"5", "start_time(3i)"=>"2", "start_time(4i)"=>"12", "start_time(5i)"=>"39"}, "1"=>{"name"=>"お米", "protein"=>"1", "fat"=>"11", "carbohydrate"=>"1", "start_time(1i)"=>"2019", "start_time(2i)"=>"5", "start_time(3i)"=>"2", "start_time(4i)"=>"08", "start_time(5i)"=>"13"}}

 

インデックスナンバーで区別された、入れ子構造のハッシュが飛んでいることがわかる。

 

def log_params(i)
params.require(:log).require(i.to_s.to_sym).permit(:name,。。。省略
end

 

params[:log][:"1"]でお米のデータが取れるため上記のようにシンボル化して値を取得できるようにする。

 

def create
i = 0
while params[:log][i.to_s.to_sym] != nil do
@log=Log.new(log_params(i))
@log.save!
i = i + 1
end
if @log.save
redirect_to new_log_path ,notice: '食事管理登録をしました'
else
flash.now[:notice] = '食事情報を入力してください'
render :new
end
end

 

インデックス番号をiと定義し、params[:log][i.to_s.to_sym]がnil出ない場合に繰り返し、

保存するロジックを組む。

 

 

 

できた。。

 

 

 

結構詰まりました。fields_forとか使ってもできるのだろう、、