has_many_attachedを使いUnpermitted parameter が発生した

Active Storageを使用して、複数のファイルを1つのレコードに添付する実装を行っていてエラーに遭遇したのでメモしておきます。

最初に結論

複数のファイルを1つのレコードに添付する場合は、permitメソッドを下記のように使う必要がありました。

params.permit(キー: [])

詳しく解説していきます。

エラーが発生した状況

# エラー内容

Unpermitted parameter: :main_images
# app/models/site.rb

has_many_attached :main_images
# edit.html.slim

= f.input :main_images, as: :file, input_html: {multiple: true}, hint: 'JPEG/PNG (1200x400)'

- if @site.main_images.attached?
        .main_images_box
          - @site.main_images.each do |main_image|
            .main_image
              = image_tag main_image.variant(resize:'300x100').processed
              = link_to '削除', admin_site_attachment_path(main_image.id), method: :delete, class: 'btn btn-danger'
# app/controllers/sites_controller.rb

def site_params
    params.require(:site).permit(:name, :subtitle, :description, :favicon, :og_image, :main_images)
end

経緯

複数の画像を一度に登録できるレコードを作成するのが目的です。
そこでActive Storagehas_many_attachedを使い、レコードとファイルの間に1対多の関係を設定しました。
viewも記述し、Webブラウザで複数の画像を登録してみたら上記に載せたUnpermitted parameter: :main_imagesというエラーが発生しました。
いつもなら_paramsメソッドのpermitの中身が抜けているorタイポ、この二択だったのですが、今回はどちらも当てはまりませんでした。

どのようにエラーを解決したか

困ったときのRailsガイド!を調べてみると載っていました。 
引用: Active Storage の概要 - Railsガイド

def message_params
  params.require(:message).permit(:title, :content, images: [])
end                                                                                                

images: []この記述だけ見ても基礎がなっていない自分には理解できなかったので、permitメソッドに載っているのかな?と思いpermitメソッドについて調べてみました。

わかりやすく解説している記事が見つかったので引用させていただきました。
【Rails】 | Pikawaka - ピカ1わかりやすいプログラミング用語サイト

バリューに複数の値が入るときは配列となってパラメーターに入ります。
例えばform_forやform_withでフォームを作成する際、collection_check_boxesで複数の値を保存するときなどに使います。

今回実装した、複数枚の画像を表示する箇所のHTMLを検証ツールを使い調べてみました。

<input multiple="multiple" class="file optional" type="file" name="site[main_images][]" id="site_main_images">

上記のようにnameのバリューが配列となっていることがわかりました。

今回の学び

  • バリューに複数の値が入るときは配列となってパラメーターに入るので、params.permit(キー: [])のような形で記述する。
  • フォームヘルバーを使った場合はHTMLを見てみると理解が深まる。
  • 実装したい機能がある場合は公式リファレンスを読み込む。