Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Deleting attachment

402 views
Skip to first unread message

ric...@devius.net

unread,
Apr 7, 2017, 7:22:01 AM4/7/17
to Shrine
I've been using Shrine for a short period of time, and I can't figure out how to delete an attachment.

I have the uploader working properly, files are saved and promoted to permanent storage and all that. The field name of the attachment in question is "avatar" and I'm using the versions plugin.

In my controller I have this code to deal with users removing the attached file:
def update
   
@user = User.find(params[:id])

   
if params["delete-avatar"]
       
if @user.avatar.delete
            flash
[:success] = "Avatar was successfully deleted."
       
else
            flash
[:danger] = "Couldn't delete current avatar."
       
end

        redirect_to edit_user_path
(@user)
       
elsif
           
# unrelated code
       
end
   
end
end

But it fails in the @user.avatar.delete line saying that:

wrong number of arguments (given 0, expected 1)


I've added the multi_delete plugin as well to the uploader class but it made no difference. The documentation mentions nothing about passing arguments to delete, so how do you delete an attachment?

ric...@devius.net

unread,
Apr 7, 2017, 7:26:25 AM4/7/17
to Shrine, ric...@devius.net
I just realized the indentation is a bit wrong in the above example. Here's the correct one:

def update
   
@user = User.find(params[:id])

   
if params["delete-avatar"]
       
if @user.avatar.delete
            flash
[:success] = "Avatar was successfully deleted."
       
else
            flash
[:danger] = "Couldn't delete current avatar."
       
end

        redirect_to edit_user_path
(@user)

   
elsif @user.update_attributes(user_params)

Janko Marohnić

unread,
Apr 7, 2017, 7:30:35 AM4/7/17
to ric...@devius.net, Shrine
You can delete the attachment by assigning `nil` to the attachment attribute and saving the record:

@user.avatar = nil
@user.save
# or
@user.update(avatar: nil)

You can also use the `remove_attachment` plugin which adds a `remove_avatar` virtual attribute to the user, and you create a checkbox in your form for that attribute, and then just call `@user.update(params[:user])` in your controller. This does the same thing under the hood.

Calling `@user.avatar.delete` isn't preferred because you also want to clear the `avatar_data` column after deleting the attachment, but it's still weird that it raises a "wrong number of arguments" error. Could you post a backtrace for that error?

P.S. Yes, the converting to code in Google groups sucks, it messes up the indentation and adds extra newlines, sorry about that :/

--
You received this message because you are subscribed to the Google Groups "Shrine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-shrine+unsubscribe@googlegroups.com.
To post to this group, send email to ruby-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ruby-shrine/0955b1fd-5995-4d9a-9fd4-063a6fb301ec%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

ric...@devius.net

unread,
Apr 7, 2017, 7:50:26 AM4/7/17
to Shrine, ric...@devius.net
Many thanks!

However I think the documentation could be improved in this case. There is no mention of how to remove a record and associated files in the Readme, and I can't see any obvious topic where this could be found in shrinerb.com. There are a few mentions of deleting on the Readme, but it seems all that does is delete the files themselves, while not touching the associated data record, but I only inferred this from your previous answer. It's not very obvious that using the delete method will not make any changes to the data.

Also, the remove_attachment plugin mentions that it's used to remove attached data with a checkbox, but I don't want to use a checkbox so that threw me off a bit.

Here's the backtrace, but I don't think it will help much:


app/controllers/users_controller.rb:58:in `delete'
app/controllers/users_controller.rb:58:in `update'
actionpack (5.0.2) lib/action_controller/metal/basic_implicit_render.rb:4:in `send_action'
actionpack (5.0.2) lib/abstract_controller/base.rb:188:in `process_action'
actionpack (5.0.2) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (5.0.2) lib/abstract_controller/callbacks.rb:20:in `block in process_action'
activesupport (5.0.2) lib/active_support/callbacks.rb:126:in `call'
activesupport (5.0.2) lib/active_support/callbacks.rb:506:in `block (2 levels) in compile'
activesupport (5.0.2) lib/active_support/callbacks.rb:455:in `call'
activesupport (5.0.2) lib/active_support/callbacks.rb:101:in `__run_callbacks__'
activesupport (5.0.2) lib/active_support/callbacks.rb:750:in `_run_process_action_callbacks'
activesupport (5.0.2) lib/active_support/callbacks.rb:90:in `run_callbacks'
actionpack (5.0.2) lib/abstract_controller/callbacks.rb:19:in `process_action'
actionpack (5.0.2) lib/action_controller/metal/rescue.rb:20:in `process_action'
actionpack (5.0.2) lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
activesupport (5.0.2) lib/active_support/notifications.rb:164:in `block in instrument'
activesupport (5.0.2) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (5.0.2) lib/active_support/notifications.rb:164:in `instrument'
actionpack (5.0.2) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
actionpack (5.0.2) lib/action_controller/metal/params_wrapper.rb:248:in `process_action'
activerecord (5.0.2) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
actionpack (5.0.2) lib/abstract_controller/base.rb:126:in `process'
actionview (5.0.2) lib/action_view/rendering.rb:30:in `process'
actionpack (5.0.2) lib/action_controller/metal.rb:190:in `dispatch'
actionpack (5.0.2) lib/action_controller/metal.rb:262:in `dispatch'
actionpack (5.0.2) lib/action_dispatch/routing/route_set.rb:50:in `dispatch'
actionpack (5.0.2) lib/action_dispatch/routing/route_set.rb:32:in `serve'
actionpack (5.0.2) lib/action_dispatch/journey/router.rb:39:in `block in serve'
actionpack (5.0.2) lib/action_dispatch/journey/router.rb:26:in `each'
actionpack (5.0.2) lib/action_dispatch/journey/router.rb:26:in `serve'
actionpack (5.0.2) lib/action_dispatch/routing/route_set.rb:725:in `call'
rack (2.0.1) lib/rack/etag.rb:25:in `call'
rack (2.0.1) lib/rack/conditional_get.rb:38:in `call'
rack (2.0.1) lib/rack/head.rb:12:in `call'
rack (2.0.1) lib/rack/session/abstract/id.rb:222:in `context'
rack (2.0.1) lib/rack/session/abstract/id.rb:216:in `call'
actionpack (5.0.2) lib/action_dispatch/middleware/cookies.rb:613:in `call'
activerecord (5.0.2) lib/active_record/migration.rb:553:in `call'
actionpack (5.0.2) lib/action_dispatch/middleware/callbacks.rb:38:in `block in call'
activesupport (5.0.2) lib/active_support/callbacks.rb:97:in `__run_callbacks__'
activesupport (5.0.2) lib/active_support/callbacks.rb:750:in `_run_call_callbacks'
activesupport (5.0.2) lib/active_support/callbacks.rb:90:in `run_callbacks'
actionpack (5.0.2) lib/action_dispatch/middleware/callbacks.rb:36:in `call'
actionpack (5.0.2) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.0.2) lib/action_dispatch/middleware/remote_ip.rb:79:in `call'
actionpack (5.0.2) lib/action_dispatch/middleware/debug_exceptions.rb:49:in `call'
web-console (3.4.0) lib/web_console/middleware.rb:135:in `call_app'
web-console (3.4.0) lib/web_console/middleware.rb:28:in `block in call'
web-console (3.4.0) lib/web_console/middleware.rb:18:in `catch'
web-console (3.4.0) lib/web_console/middleware.rb:18:in `call'
actionpack (5.0.2) lib/action_dispatch/middleware/show_exceptions.rb:31:in `call'
railties (5.0.2) lib/rails/rack/logger.rb:36:in `call_app'
railties (5.0.2) lib/rails/rack/logger.rb:24:in `block in call'
activesupport (5.0.2) lib/active_support/tagged_logging.rb:69:in `block in tagged'
activesupport (5.0.2) lib/active_support/tagged_logging.rb:26:in `tagged'
activesupport (5.0.2) lib/active_support/tagged_logging.rb:69:in `tagged'
railties (5.0.2) lib/rails/rack/logger.rb:24:in `call'
sprockets-rails (3.2.0) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (5.0.2) lib/action_dispatch/middleware/request_id.rb:24:in `call'
rack (2.0.1) lib/rack/method_override.rb:22:in `call'
rack (2.0.1) lib/rack/runtime.rb:22:in `call'
activesupport (5.0.2) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
actionpack (5.0.2) lib/action_dispatch/middleware/executor.rb:12:in `call'
actionpack (5.0.2) lib/action_dispatch/middleware/static.rb:136:in `call'
rack (2.0.1) lib/rack/sendfile.rb:111:in `call'
railties (5.0.2) lib/rails/engine.rb:522:in `call'
puma (3.6.2) lib/puma/configuration.rb:225:in `call'
puma (3.6.2) lib/puma/server.rb:578:in `handle_request'
puma (3.6.2) lib/puma/server.rb:415:in `process_client'
puma (3.6.2) lib/puma/server.rb:275:in `block in run'
puma (3.6.2) lib/puma/thread_pool.rb:116:in `block in spawn_thread'

Note that in the error page's console I can verify that the avatar attribute is valid:


>> @user.avatar
=> {
   
:larger => #<AvatarUploader::UploadedFile:0x007ff6327791d0 @data={"id"=>"5177b9d0466fdc0367a7031f485c590b.jpg", "storage"=>"store", "metadata"=>{"filename"=>"shrine20170406-25978-71djn3.jpg", "size"=>14147, "mime_type"=>"image/jpeg"}}>,
   
:large => #<AvatarUploader::UploadedFile:0x007ff632779040 @data={"id"=>"79f7817eac1adc788431a7405bd661f7.jpg", "storage"=>"store", "metadata"=>{"filename"=>"shrine20170406-25978-71djn320170406-25978-1wxr58t.jpg", "size"=>11248, "mime_type"=>"image/jpeg"}}>,
   
:medium => #<AvatarUploader::UploadedFile:0x007ff632778eb0 @data={"id"=>"05c980fb34acfa9179302d7bf57f0293.jpg", "storage"=>"store", "metadata"=>{"filename"=>"shrine20170406-25978-71djn320170406-25978-h8zci3.jpg", "size"=>4805, "mime_type"=>"image/jpeg"}}>
 
}


Janko Marohnić

unread,
Apr 8, 2017, 9:45:17 PM4/8/17
to Ricardo Graça, Shrine
However I think the documentation could be improved in this case. There is no mention of how to remove a record and associated files in the Readme, and I can't see any obvious topic where this could be found in shrinerb.com. There are a few mentions of deleting on the Readme, but it seems all that does is delete the files themselves, while not touching the associated data record, but I only inferred this from your previous answer.

Shrine has different layer of abstractions. At the lowest level you have a storage class, a `Shrine` subclass (an "uploader") and a `Shrine::UploadedFile` object; this layer doesn't know anything about attachments or records, and this is where you saw the "Deleting" section, which talked only about deleting files through the uploader. If you scroll down to the "Attachment" section, you'll see the code examples for attachment removal (i.e. de-assigning the attachment + deleting the file).

In the past I've had the higher-level "attachment" interface explained first, and then went to the low levels, but then there were many questions arriving on how to use Shrine at the lower level and how it works, so I decided that it's better to explain Shrine's API bottom-up.

Also, the remove_attachment plugin mentions that it's used to remove attached data with a checkbox, but I don't want to use a checkbox so that threw me off a bit.

Yes, that's true, the remove_attachment plugin is only useful for checkboxes, I just suggested it as an alternative if you're by any chance using them.

Here's the backtrace, but I don't think it will help much

Ok, I see now that the reason why calling `#delete` didn't work is that the attachment is a Ruby hash of `Shrine::UploadedFile` objects ("versions"), not a single `Shrine::UploadedFile` object. So that means what you were actually calling was `Hash#delete`, which requires an argument (but isn't what you want).

Thanks for the feedback, I will update the documentation to make the distinction between deleting files and removing attachments clearer.

Kind regards,
Janko

--
You received this message because you are subscribed to the Google Groups "Shrine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ruby-shrine+unsubscribe@googlegroups.com.
To post to this group, send email to ruby-...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages