Rails 6.0でとあるアプリを作っているのですが、ActiveStorageを使って画像を添付しています。登録は比較的簡単に行えたのですが、画面から画像のみ削除する方法がいまいちわからなかったので調査しました。
コード(修正前)
モデル
複数の画像が添付できるように、has_many_attached
にしています。
class Post < ApplicationRecord has_many_attached :images end
ビュー
simple_formを使っています。画像はActiveStorageのダイレクトアップロードでアップロードしています。
= simple_form_for(@post) do |f| = f.error_notification .form-inputs = f.input :title = f.input :content .mb-3 = f.label :images = f.file_field :images, direct_upload: true, multiple: true, accept: 'image/*' .form-actions hr = f.button :submit, data: {disable_with: t('helpers.button.disable_with')}, class: 'btn-primary mr-2' = link_to t('helpers.links.cancel'), posts_path, class: 'btn btn-secondary'
コントローラー
特に変わりはないのでstrong_parametersのところだけ書いておきます。
class PostsController < ApplicationController # 略 private def post_params params.require(:post).permit( :title, :content, images: [], ) end end
やろうとしたアイデア
こういうモデルの子になるデータの追加・削除はaccepts_nested_attributes_for
を使うのが順当だろうと思いました。
試したこと(失敗したやつ)
モデルを以下のように修正。
class Post < ApplicationRecord has_many_attached :images accepts_nested_attributes_for :images, allow_destroy: true end
ビューを以下のように修正。
= simple_form_for(@post) do |f| / 略 .form-inputs / 略 .mb-3 = f.label :images = f.file_field :images, direct_upload: true, multiple: true, accept: 'image/*' .row.mb-3 = f.fields_for :images do |image| .col.col-sm-6.col-md-4.mb-3 = image.hidden_field :id .form-check label = image.check_box :_destroy, { class: 'form-check-input mr-1', checked: false }, true, false | 削除する = image_tag url_for(image.object), class: 'img-thumbnail rounded' / 略
こうすると、accepts_nested_attributes_for
に:images
なんていう関連はない!と言われて落ちます。
しかし、AcitveStorage::Attachment
モデルと関連があるはず…なので、次を試みます。
試したこと(成功したやつ)
モデルを以下のように修正。
class Post < ApplicationRecord has_many_attached :images accepts_nested_attributes_for :images_attachments, allow_destroy: true end
ビューを以下のように修正。
= simple_form_for(@post) do |f| / 略 .form-inputs / 略 .mb-3 = f.label :images = f.file_field :images, direct_upload: true, multiple: true, accept: 'image/*' .row.mb-3 = f.fields_for :images_attachments do |image| .col.col-sm-6.col-md-4.mb-3 = image.hidden_field :id .form-check label = image.check_box :_destroy, { class: 'form-check-input mr-1', checked: false }, true, false | 削除する = image_tag url_for(image.object), class: 'img-thumbnail rounded' / 略
コントローラーもstrong_parametersを修正します。
class PostsController < ApplicationController # 略 private def post_params params.require(:post).permit( :title, :content, images: [], images_attachments_attributes: [ :id, :_destroy ], ) end end
これで、更新時にファイルの削除ができるようになりました。
動作検証
紫陽花と桜の画像をアップ済みです。そこから、紫陽花の画像を削除してみます。
showの画面を都合で見せられないのですが、再び更新画面にきたときには桜の画像のみ残っています。
削除に成功です。