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 from a collection.
The problem: For some reason all my images immediately get purged/deleted whenever I load the show page of a collection. Of course I only want to delete a file whenever I click the link. Does anyone know how to solve this problem?
My collection show view:
<div id="gallery">
<% @collection.images.each do |image| %>
<%= image_tag(image) %>
<%= link_to 'Remove image', image.purge %>
<% end %>
</div>
I've read documentation on http://edgeguides.rubyonrails.org/active_storage_overview.html#removing-files (see paragraph 4)
but sadly this doesn't give any information on how to specifically use the purge or purge_later method.
EDIT Currently changed my code to this (which still sadly doesn't work):
<div id="gallery">
<% @collection.images.each do |image| %>
<%= image_tag(image) %>
<%= link_to 'Remove', delete_image_attachment_collections_url(image.signed_id),
method: :delete,
data: { confirm: 'Are you sure?' } %>
<% end %>
</div>
With this in my collections_controller.rb
def delete_image_attachment
@image = ActiveStorage::Blob.find_signed(params[:id])
@image.purge
redirect_to root_path
end
Which is giving me this error after I tried to delete an attached image:
Server log:
Started DELETE "/collections/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBYdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3e75276d414b4c2040e02cf0afbc083e2337faa0/delete_image_attachment" for ::1 at 2018-03-29 19:06:55 +0200
Processing by CollectionsController#delete_image_attachment as HTML
Parameters: {"authenticity_token"=>"60zIkeknxRYp/sJIWNwF+BrEftYHSCQvak34h8FkadPXgVPQSXN/sCoxI/6FU+jZbqQitES81fyqkmIx6XYp6w==", "id"=>"eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBYdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3e75276d414b4c2040e02cf0afbc083e2337faa0"}
ActiveStorage::Blob Load (0.1ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 LIMIT $2 [["id", 90], ["LIMIT", 1]]
↳ app/controllers/collections_controller.rb:69
Disk Storage (0.1ms) Deleted file from key: 8wpzqPQcWYjK2rVEejcU88FB
Disk Storage (0.0ms) Deleted files by key prefix: variants/8wpzqPQcWYjK2rVEejcU88FB/
(0.0ms) BEGIN
↳ app/controllers/collections_controller.rb:70
ActiveStorage::Blob Destroy (0.2ms) DELETE FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 [["id", 90]]
↳ app/controllers/collections_controller.rb:70
(2.0ms) COMMIT
↳ app/controllers/collections_controller.rb:70
ActiveStorage::Attachment Load (0.2ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = $1 AND "active_storage_attachments"."record_type" = $2 AND "active_storage_attachments"."name" = $3 LIMIT $4 [["record_id", 90], ["record_type", "ActiveStorage::Blob"], ["name", "preview_image"], ["LIMIT", 1]]
↳ app/controllers/collections_controller.rb:70
Redirected to http://localhost:3000/
Completed 302 Found in 5ms (ActiveRecord: 2.5ms)
Output of rake routes
:
Prefix Verb URI Pattern Controller#Action
root GET / home#index
about GET /about(.:format) pages#about
contact GET /contact(.:format) pages#contact
settings GET /settings(.:format) settings#edit
new_setting GET /setting/new(.:format) settings#new
edit_setting GET /setting/edit(.:format) settings#edit
setting GET /setting(.:format) settings#show
PATCH /setting(.:format) settings#update
PUT /setting(.:format) settings#update
DELETE /setting(.:format) settings#destroy
POST /setting(.:format) settings#create
delete_image_attachment_collection DELETE /collections/:id/delete_image_attachment(.:format) collections#delete_image_attachment
collections GET /collections(.:format) collections#index
POST /collections(.:format) collections#create
new_collection GET /collections/new(.:format) collections#new
edit_collection GET /collections/:id/edit(.:format) collections#edit
collection GET /collections/:id(.:format) collections#show
PATCH /collections/:id(.:format) collections#update
PUT /collections/:id(.:format) collections#update
DELETE /collections/:id(.:format) collections#destroy
rails_service_blob GET /rails/active_storage/blobs/:signed_id/*filename(.:format) active_storage/blobs#show
rails_blob_representation GET /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) active_storage/representations#show
rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
My 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 'instellingen', to: 'settings#edit'
resource :setting
resources :collections do
member do
delete :delete_image_attachment
end
end
end
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?
My files
View: collection/show.html.erb:
Controller: collections_controller.rb
Model: collection.rb
Routes: routes.rb
Thanks for your update regarding Blob vs Attachment! After purging the attachment I redirect_back to the form I came from like this:
Not the best solution to reload the entire page but works ...
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 yourdelete_image_attachment
path.The destroy method would look something like this...
The route should be something like so...
Check out the rails routing guide for more fun routing facts.