パラメーターが配列の場合、ストパラのparams.permitに含める方法
状況
1つのusersテーブルに対して、同時に複数のレコードを作成するために下記のようなパラメーターを送りました。
Parameters: {"users"=>[{"name"}=>{"satoshi"}, {"name"}=>{"yuta"}]}
受けるストパラは下記
private
def users_params
params.require(:users).permit(
:id,
:name
)
end
発生したエラー
requireした後にpermitメソッドを使うと、
「permit?そんなメソッドは知らんよ」と言われてしまいました。
[1] pry(#<UsersController>)> params.require(:users).permit
NoMethodError: undefined method `permit'
for #<Array:0x00007f2024a3ee40>from (pry):62:in `users_params'
(binding.pryの結果を出力しています)
理由
params.require(:publisheds)はArrayクラスだから、permitメソッドが使えない。
[2] pry(#<UsersController>)> params.require(:users).class
=> Array
[3] pry(#<UsersController>)> params.require(:users).respond_to?("permit")
=> false
情報:配列番号を指定するとpermitが通る
[4] pry(#<UsersController>)> params.require(:users)[0].respond_to?("permit")
=> true
[5] pry(#<UsersController>)> params.require(:users)[0].permit(:name)
=> <ActionController::Parameters {"name"=>"satoshi"} permitted: true>
配列(Array)で来てるなら、1個ずつ取り出せばいいんじゃね?って思いました。
解決法
mapで回して、配列をばらしてpermitして返す
private
def users_params
params.require(:users).map do |user|
user.permit(
:id,
:name
)
end
end
mapが使えた理由
ブロックを評価して配列を戻り値として持つ=rubyの仕様は、最後に評価した値を暗黙的に返す(returnする)から。
eachが使えないのはなぜ?
配列を回して引数を取るけど、その中でpermitをしても値を返さないから?
permitメソッド自体が、値の変更(代入)ではなく、許可だから少し挙動が違う?
細かな違いが難しい。。。
rubyマスターの方がいらっしゃいましたら質問させてほしいです。
参考:るりまのリンク
eachの仕様
https://docs.ruby-lang.org/ja/latest/method/Array/i/each.html
mapの仕様
https://docs.ruby-lang.org/ja/latest/class/Array.html#I_COLLECT