Closed creamstew closed 5 years ago
下記の記事の見よう見まねで機能自体は実装することができました。
しかし下記のコードがあまり理解できず、もし可能でしたら解説いただけないでしょうか。
ストロングパラメーター
params[:user][:car_selections_attributes].each { |index, hash| \
hash[:_destroy] = hash[:maker].blank? }
view
<% car_selections = @user.car_selections.map {|record| [record.maker, record] }.to_h %>
<% CarSelection.makers.each_with_index do |(maker, value), index| %>
<label>
<% car_selection = car_selections[maker] %>
<% name_prefix = "user[car_selections_attributes][#{index}]" %>
<%= hidden_field_tag "#{name_prefix}[id]", car_selection.try(:id) %>
<% checked = car_selection.present? && !car_selection.marked_for_destruction? %>
<%= check_box_tag "#{name_prefix}[maker]", maker, checked %>
<%= maker %>
</label>
<% end %>
確認しますー
元記事がviewで変数代入していて割と汚いコードだなと思ったらチェリー本書いたito sanの回答だった
元記事を参考に解説しますね。
params[:user][:car_selections_attributes].each { |index, hash| hash[:_destroy] = hash[:maker].blank? }
まずこの部分はストロングパラメータではないです。リクエストパラメータを前処理している感じですね。params.requireの処理をした結果がストロングパラメータです。 ネスト(入れ子状態になった)したハッシュをeachというメソッドで処理しています。 ハッシュのeachについては下記を参照ください each, each_pair (Hash) - Rubyリファレンス
ハッシュをeachで処理するとkeyとvalueのペアがループで処理できるようになります。 どういったリクエストパラメータが出力されているかはターミナルで実際にリクエストを発生させてみて出力をみるとかbinding.pryで実行を止めて確認してみると良いです:bow: paramsの中身を見れば確認できます。
hash[:_destroy] = hash[:maker].blank?
の部分はチェックボックスで選択されていなかったらhash[:maker]のvalueとしてnilとか空文字が入ってくるのでその場合にtrueを設定して削除対象にするようなことをしています。
多分こんな感じのイメージでリクエストパラメータがきてるのでmakerに値が入っていなかったらtrueを設定するみたいなことをしていると思います:bow:
{
"user" => {
"car_selections_attributes" => {
"0" => {
"maker" => 'toyota'
},
"1" => {
"maker" => 'nissan'
}
"2" => {
"maker" => ""
}
}
}
}
続いてviewの方ですが
<% car_selections = @user.car_selections.map {|record| [record.maker, record] }.to_h %>
の部分は配列をhashに変換している感じですね
【Ruby】Array から Hash を作る方法7選(a.k.a. やっぱり Array#zip はかわいいよ) | RakSul Tech Blog
<% CarSelection.makers.each_with_index do |(maker, value), index| %>
の部分はまたhashをeach_with_indexというメソッドで処理している感じですね ハッシュからeach_with_indexでkeyとvalとindexを取り出す。 - bismar's blog
ざっくり説明しました:bow:不明な点あれば追記してください:bow:補足しますmm
丁寧な解説ありがとうございます。 また、質問したにも関わらずご返信遅れ申し訳ありません。
params[:user][:car_selections_attributes].each { |index, hash| hash[:_destroy] = hash[:maker].blank? }
についてはおかげさまで理解できました。
viewの部分で追加で何点か質問させてください。
<% checked = car_selection.present? && !car_selection.marked_for_destruction? %>
の!が文頭に来ているのはどういった意味でしょうか?
<% CarSelection.makers.each_with_index do |(maker, value), index| %>
のvalueはmakerを配列のインデックスでいちいち取り出さないために記載している意味合いでしょうか?
<%= hidden_field_tag "#{name_prefix}[id]", car_selection.try(:id) %>
のcar_selection.try(:id)はどういう意味で記載しているのかがわかりません。
!が文頭に来ているのはどういった意味でしょうか?
論理の否定ですね変数がtrueの時にfalse, falseの時にtrueを返すようになります:bow: https://blog.codecamp.jp/posts-34186
<% CarSelection.makers.each_with_index do |(maker, value), index| %> のvalueはmakerを配列のインデックスでいちいち取り出さないために記載している意味合いでしょうか?
これは #each_with_index
というメソッドのブロック変数の書き方ですね
hashのkeyとvalueをブロック変数にマッピングするために使っています:bow:
http://bismar.hatenablog.com/entry/2012/12/01/215111
<%= hidden_field_tag "#{name_prefix}[id]", car_selection.try(:id) %>
tryが対象のkey(今回は:id
)が存在する時にそのメソッドを実行して存在しない場合はnilを返すというメソッドなのでcar_selectionが存在する時にそのIDを返して存在しない場合はnilを設定している感じですね
イメージはこんな感じ
[1] pry(main)> class Hoge
[1] pry(main)* def id
[1] pry(main)* 'unko!!'
[1] pry(main)* end
[1] pry(main)* end
=> :id
[2] pry(main)> Hoge.new.try(:id)
=> "unko!!"
[3] pry(main)> nil.try(:id)
=> nil
ありがとうございます。おかげでしっかりと理解することができました!!
概要
複数選択可能なチェックボックスを作成し、選択した値のみをそれぞれDBに保存したいが一番最後にチェックをつけた項目しかDBに保存されない。 Userモデルとuser_genreモデルは一対多の関係
実現したいこと
1.選択した値のみをそれぞれDBに保存したい。 2.updateする際にチェックを外した場合はレコードをデリートしたい
困っていること
1.選択した値のみをそれぞれDBに保存できない。 2.updateする際にチェックを外した際にレコードをデリートしたい
下記の記事が自分のやりたいことと同じなのですが、記事内のviewとストロングパラメータの記載部分が理解できていません。
https://ja.stackoverflow.com/questions/14891/rails%E3%81%AE%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%81%A7%E3%83%9E%E3%83%AB%E3%83%81%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%E3%82%92%E5%AE%9F%E7%8F%BE%E3%81%97%E3%81%9F%E3%81%84
ストロングパラメーター
view
自分のコード
user.rb
user_genre.rb
user_controllerのストロングパラメーター
_form.rb
問題となっている箇所の予想
一番最後にチェックをつけた値に書き換わってしまうため。
問題となっているアプリケーションのGitHub URL
https://github.com/creamstew/multi_check_box