EDIT: TLDR: This boils down to serializing the attachments. See my response.
I can see two ways to achieve this:
(1) Serialize the attachments (with id
and url
attributes), thus providing an id
to the FE that they can use to DELETE /attachments/:id
which would then call ActiveStorage::Attachment.find(:id).purge
. The problem is with serializing as attachments do not have built-in models. I tried creating an ActiveStorageAttachment
model for the active_storage_attachments
table but could not get the url for the attachment as the Rails.application.routes.url_helpers.url_for(@object)
requires an ActiveStorage::Attachment
object not an ActiveStorageAttachment
object.
(2) Another option would be to have a DELETE /attachments/:attachment_url
endpoint. For this to work, I'd need to get the ActiveStorage::Attachment
object based on the url, in order to call purge
on it. Not sure if that is possible?
I'd much prefer the first solution, it feels cleaner and more adaptable. Any help with either approach would be much appreciated!
In the end, I managed to serialize the attached images (option(1) above) using the jsonapi-rb
gem.
In the controller, I include: :images
and pass in the attachment type using the expose
option:
class PostsController < ApplicationController
...
def show
respond_to do |format|
format.html
format.json { render jsonapi: @post, include: :images, expose: {attachment_type: "images"} }
end
end
end
ActiveSupport gives you the post.images_attachments
method for free:
class SerializablePost < JSONAPI::Serializable::Resource
type 'posts'
...
has_many :images do
@object.images_attachments
end
end
I created an attachment serializer:
class SerializableAttachment < JSONAPI::Serializable::Resource
include Rails.application.routes.url_helpers
type do
@attachment_type
end
attribute :id
attribute :url do
url_for(@object)
end
end
I needed to tell jsonapi to use this serializer for all attachments:
class ApplicationController < ActionController::Base
...
def jsonapi_class
super.merge(
'ActiveStorage::Attachment': SerializableAttachment
)
end
end
Now I can implement DELETE /attachments/:id
.