form_with .date_select 保存できない パラメータ
Railsのフォームヘルパーであるform_with であるが、面倒なところがまたあった。
form_withのメソッドで年月日をセレクトボックスで入力できるようにする.date_select というものがある。これ、便利だけれど、パラメータの保存が面倒だったので備忘録。
form_withの使い方はここのサイトにある通り。引数で様々なオプションを指定することになるので、ここでよく確認しておこう。
https://pikawaka.com/rails/form_with#form.date_select
さて、今回はプロフィール登録画面で生年月日を入力するフォームを作った。
※ HTMLはhamlで書いています。
(Viewファイル)
sprintfというちょっと特殊な書き方をしているのは年月日の区切りを入れるためです。
以下のサイトを参考に
● https://yoshiob.hatenadiary.org/entry/20091105
この記述で送られるパラメータをUsers_ControllerのupdateアクションからUsers_Tableのbirth_dayカラムに保存できるようにしたい。
このViewのフォームから送られるパラメータは
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ibjRO〜〜i6xZnQ8Txdw==",
"user"=>{"name"=>"ほげ" , "nickname"=>"ほげちゃん", "profile"=>"ほげほげ"},
"birth_day"=>{"birth_day(1i)"=>"2000", "birth_day(2i)"=>"1", "birth_day(3i)"=>"1"},
"commit"=>"登録する", "id"=>"1"}
このような構造になる。注目すべきは三段目。
● 今回はform_withによってUserモデルにアクセスするパラメータを作ったので、入力フォームに記述した内容はParams: { user: { ここに入力内容 }}というように二重のハッシュで格納されるはずである。
しかしbirth_day の内容はuser:{ }の外に作られる。これの何が問題か、というと、ストロングパラメータを作る際にrequire(:user)をつけるところでエラーになる。
requireメソッドで二重構造のハッシュを解消しているが、その中にbirth_dayのキーがないので、permitメソッドを適用できなくて、Parameter_permittion_errorみたいなのになる。
● もう一点、birth_dayキーの中身を見てみると、入力した年月日の情報がバラけてそれぞれ"birth_day(1i)"的なキーとバリューで保存されている。このままだとDBのuserテーブルにあるbirth_dayカラムにきちんとまとめて保存されない。(birth_dayカラムのデータ型はDATE型にしている)
このバラバラになっているデータをひとまとめにする必要がある。
これらの状況を解決していく。備忘録。
●コントローラの記述
① params[:user][:birth_day] = birthday_join
この記述でまず右辺のbirthday_joinメソッドを起動させる。返り値をparamsのuserキーの中にbirth_dayキーとして新たに保存する。これでストロングパラメータのrequire問題を解決する。(この辺カラム名との整合性に注意)
② birthday_joinメソッドの中身
・ date = params[:birth_day] … paramsの中の:birth_dayハッシュの値を取得
・ if date["birth_day(1i)"].empty? && date["birth_day(2i)"].empty? 〜〜
…入力が空だった時のエラー回避、空のままで値を返す記述
・ Date.new(date["birth_day(1i)"].to_i,date["birth_day(2i)"].to_i,date["birth_day(3i)"].to_i)
…バラけてたデータをto_iメソッドで数値化して、それをDateクラスで改めてDate型のインスタンスとして再構成する。このインスタンスを元のParamsに戻します。
これにて
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ibjRO〜〜i6xZnQ8Txdw==",
"user"=>{"name"=>"ほげ" , "nickname"=>"ほげちゃん", "profile"=>"ほげほげ",
"birth_day"=>{"2000-1-1"},"commit"=>"登録する", "id"=>"1"}
になって全ての入力内容がuser: { }のハッシュに入ったので、ストロングパラメータでPermittionがかけられてエラーが起きなくなりました。
このように.date_selectはパラメータの値が面倒臭いので気をつけて実装しましょう。
<参考サイト>
● https://qiita.com/ozackiee/items/3c027d07cdeb61df6029