web-dev-qa-db-fra.com

Rails 5.2 Active Storage purge/supprime les pièces jointes

J'utilise donc Active Storage pour télécharger plusieurs images attachées à un modèle Collection. Tout fonctionne bien sauf lorsque j'essaie de purger/supprimer une seule pièce jointe d'une collection. 

Le problème: Pour une raison quelconque, toutes mes images sont immédiatement purgées/supprimées chaque fois que je charge la page de démonstration d'une collection. Bien sûr, je veux seulement supprimer un fichier chaque fois que je clique sur le lien. Est-ce que quelqu'un sait comment résoudre ce problème?

Ma collection Voir la vue:

<div id="gallery">
  <% @collection.images.each do |image| %>
    <%= image_tag(image) %>
    <%= link_to 'Remove image', image.purge %>
  <% end %>
</div>

J'ai lu la documentation sur http://edgeguides.rubyonrails.org/active_storage_overview.html#removing-files (Voir paragraphe 4)

mais malheureusement, cela ne donne aucune information sur la manière d'utiliser spécifiquement la méthode purge ou purge_later.

EDIT Mon code a été changé pour ceci (qui ne fonctionne malheureusement toujours pas):

<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>

Avec cela dans collections_controller.rb

  def delete_image_attachment
    @image = ActiveStorage::Blob.find_signed(params[:id])
    @image.purge
    redirect_to root_path
  end

Ce qui me donne cette erreur après avoir essayé de supprimer une image jointe:

 Error I get when returning to the collection show after (trying to) delete an image.

Journal du serveur:

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)

Sortie de 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

Mes 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
8
royketelaar

Vous parcourez la collection d’images et appelez la méthode de purge pour chacune d’elles. Au lieu de cela, vous devriez créer un lien vers une méthode de destruction sur votre contrôleur, comme ci-dessous, en tenant compte des actions de votre contrôleur et en devinant les noms de votre route.

L'erreur est due au fait que l'objet image renvoie son chemin d'accès complet et que le lien indique ce que vous souhaitez indiquer. Au lieu de cela, vous voulez juste son signed_id et que le lien appelle la route qui a votre chemin delete_image_attachment.

 <%= link_to 'Remove', delete_image_attachment_collections_url(image.signed_id),
                method: :delete,
                data: { confirm: 'Are you sure?' } %>

La méthode destroy ressemblerait à quelque chose comme ça ...

def delete_image_attachment
  @image = ActiveStorage::Blob.find_signed(params[:id])
  @image.purge
  redirect_to collections_url
end

La route devrait être quelque chose comme si ...

resources :collections do
  member do
    delete :delete_image_attachment
  end
end

Consultez le Guide de routage Rails pour plus de faits de routage amusants.

10
dbugger

Merci pour votre mise à jour concernant Blob vs Attachment! Après avoir purgé la pièce jointe, je redirige vers le formulaire d'où je viens:

def remove_attachment
  attachment = ActiveStorage::Attachment.find(params[:id])
  attachment.purge # or use purge_later
  redirect_back(fallback_location: collections_path)
end

Pas la meilleure solution pour recharger la page entière mais fonctionne ...

3
Max Weber

Okay en quelque sorte résolu mon problème mais je ne comprends pas vraiment ce qui se passe.

Chaque fois que je clique sur le bouton "Supprimer", le message d'erreur suivant s'affiche:  

Il veut rediriger vers l'URL collection_url avec l'ID 43 (alors que l'ID de ma collection est en réalité 6, 43 est probablement l'ID de la pièce jointe de l'image).

Lorsque je recharge manuellement la même page de collection, la photo a disparu (donc cela fonctionne en quelque sorte), mais rien de tout cela n’est bien sûr idéal.

Est-ce que quelqu'un sait comment je peux améliorer mon code pour que le redirect_to de mon contrôleur pointe vers l'ID de collection actuel au lieu de l'ID de pièce jointe d'image Activestorage?

Mes dossiers

Voir: 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

Modèle: 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
1
royketelaar