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
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.
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 ...
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
If you arrived here looking for a way to delete an attachment via the rails console :
user.image.purge
Source: https://edgeguides.rubyonrails.org/active_storage_overview.html#removing-files
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.