So I\'m using Active Storage to upload multiple images attached to a Collection model. Everything works well except whenever I\'m trying to purge/delete a single attachment
You are looping through the collection of images and calling the purge method on each one. Instead you should be linking to a destroy method on your controller, something like the below taking into account your controller actions and guessing at your route names.
The error is because image object returns its full path and the link thinks that what you want to point to. Instead you just want its signed_id
and want the link to call the route that has your delete_image_attachment
path.
<%= link_to 'Remove', delete_image_attachment_collections_url(image.signed_id),
method: :delete,
data: { confirm: 'Are you sure?' } %>
The destroy method would look something like this...
def delete_image_attachment
@image = ActiveStorage::Blob.find_signed(params[:id])
@image.purge
redirect_to collections_url
end
The route should be something like so...
resources :collections do
member do
delete :delete_image_attachment
end
end
Check out the rails routing guide for more fun routing facts.
Okay I sort of solved my problem but I don't really understand what's happening.
Whenever I click on the "Remove" button I get this error:
It wants to redirect to the collection_url with ID 43 (while the ID of my collection is actually 6, 43 is probably the ID of the image attachment).
When I reload the same collection page manually, the picture is gone (so it sort of works) but nothing of this is ofcourse ideal.
Does someone know how I can improve my code so that the redirect_to in my controller points to the current collection ID instead of the Activestorage image attachment ID?
View: collection/show.html.erb:
<div id="gallery">
<% @collection.images.each do |image| %>
<%= image_tag(image) %>
<%= link_to 'Remove', delete_image_attachment_collection_url(image),
method: :delete,
data: { confirm: 'Are you sure?' } %>
<% end %>
</div>
Controller: collections_controller.rb
class CollectionsController < ApplicationController
before_action :set_collection, only: [:show, :edit, :update, :destroy]
before_action :set_collections
# GET /collections
# GET /collections.json
def index
end
# GET /collections/1
# GET /collections/1.json
def show
end
# GET /collections/new
def new
@collection = Collection.new
end
# GET /collections/1/edit
def edit
end
# POST /collections
# POST /collections.json
def create
@collection = Collection.new(collection_params)
respond_to do |format|
if @collection.save
format.html { redirect_to @collection, notice: 'Fotocollectie is aangemaakt.' }
format.json { render :show, status: :created, location: @collection }
else
format.html { render :new }
format.json { render json: @collection.errors, status: :unprocessable_entity }
end
end
# collection = Collection.create!(collection_params)
# redirect_to collection
end
# PATCH/PUT /collections/1
# PATCH/PUT /collections/1.json
def update
respond_to do |format|
if @collection.update(collection_params)
format.html { redirect_to @collection, notice: 'Fotocollectie is bijgewerkt.' }
format.json { render :show, status: :ok, location: @collection }
else
format.html { render :edit }
format.json { render json: @collection.errors, status: :unprocessable_entity }
end
end
end
# DELETE /collections/1
# DELETE /collections/1.json
def destroy
@collection.destroy
respond_to do |format|
format.html { redirect_to collections_url, notice: 'Fotocollectie is verwijderd.' }
format.json { head :no_content }
end
end
def delete_image_attachment
@image = ActiveStorage::Attachment.find(params[:id])
@image.purge
redirect_to @current_page
end
private
# Use callbacks to share common setup or constraints between actions.
def set_collection
@collection = Collection.find(params[:id])
end
def set_collections
@collections = Collection.all
end
# Never trust parameters from the scary internet, only allow the white list through.
def collection_params
params.require(:collection).permit(:title, :order, images: [])
end
end
Model: collection.rb
class Collection < ApplicationRecord
has_many_attached :images
end
Routes: routes.rb
Rails.application.routes.draw do
root 'home#index'
get 'about', to: 'pages#about', as: :about
get 'contact', to: 'pages#contact', as: :contact
get 'settings', to: 'settings#edit'
resource :setting
resources :collections do
member do
delete :delete_image_attachment
end
end
end
The following didn't work for me.
def delete_image_attachment
@image = ActiveStorage::Blob.find_signed(params[:id])
@image.purge
redirect_to collections_url
end
So what i did is found the attachment and purged it. You can do purge_later which is recommended.
def delete_image_attachment
@image = ActiveStorage::Blob.find_signed(params[:id])
@image.attachments.first.purge
redirect_to collections_url
end
This removed both attachment and blob record.
Thanks for your update regarding Blob vs Attachment! After purging the attachment I redirect_back to the form I came from like this:
def remove_attachment
attachment = ActiveStorage::Attachment.find(params[:id])
attachment.purge # or use purge_later
redirect_back(fallback_location: collections_path)
end
Not the best solution to reload the entire page but works ...