Files
nairobi/app/models/direct_upload.rb
Javi Martín e0e35298d5 Use Active Storage to handle cached attachments
This fixes a few issues we've had for years.

First, when attaching an image and then sending a form with validation
errors, the image preview would not be rendered when the form was
displayed once again. Now it's rendered as expected.

Second, when attaching an image, removing it, and attaching a new
one, browsers were displaying the image preview of the first one. That's
because Paperclip generated the same URL from both files (as they both
had the same hash data and prefix). Browsers usually cache images and
render the cached image when getting the same URL.

Since now we're storing each image in a different Blob, the images have
different URLs and so the preview of the second one is correctly
displayed.

Finally, when users downloaded a document, they were getting files with
a very long hexadecimal hash as filename. Now they get the original
filename.
2022-02-23 18:21:38 +01:00

62 lines
1.9 KiB
Ruby

class DirectUpload
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :resource, :resource_type, :resource_id,
:relation, :resource_relation,
:attachment, :cached_attachment, :user
validates :attachment, :resource_type, :resource_relation, :user, presence: true
validate :parent_resource_attachment_validations,
if: -> { attachment.present? && resource_type.present? && resource_relation.present? && user.present? }
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
if @resource_type.present? && @resource_relation.present? && (@attachment.present? || @cached_attachment.present?)
@resource = @resource_type.constantize.find_or_initialize_by(id: @resource_id)
# Refactor
@relation = if @resource.respond_to?(:images) &&
((@attachment.present? && !@attachment.content_type.match(/pdf/)) || @cached_attachment.present?)
@resource.images.send("build", relation_attributtes)
elsif @resource.class.reflections[@resource_relation].macro == :has_one
@resource.send("build_#{resource_relation}", relation_attributtes)
else
@resource.send(@resource_relation).build(relation_attributtes)
end
@relation.user = user
end
end
def save_attachment
@relation.storage_attachment.blob.save!
end
def persisted?
false
end
private
def parent_resource_attachment_validations
@relation.valid?
if @relation.errors.key? :attachment
errors.add(:attachment, @relation.errors.full_messages_for(:attachment))
end
end
def relation_attributtes
{
storage_attachment: @attachment,
cached_attachment: @cached_attachment,
user: @user
}
end
end