demarches-normaliennes/app/graphql/extensions/attachment.rb
2024-08-22 09:26:48 +02:00

67 lines
1.9 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# frozen_string_literal: true
# references:
# https://evilmartians.com/chronicles/active-storage-meets-graphql-pt-2-exposing-attachment-urls
module Extensions
class Attachment < GraphQL::Schema::FieldExtension
attr_reader :attachment_assoc, :root
def apply
# Here we try to define the ActiveRecord association name:
# - it could be set explicitly via extension options
# - or we imply that is the same as the field name w/o "_url"
# suffix (e.g., "avatar_url" => "avatar")
@attachment_assoc = if options.key?(:attachment)
"#{options[:attachment]}_attachment"
elsif options.key?(:attachments)
"#{options[:attachments]}_attachments"
else
attachment = field.original_name.to_s.sub(/_url$/, "")
"#{attachment}_attachment"
end
@root = options&.dig(:root) || :object
end
# This method resolves (as it states) the field itself
# (it's the same as defining a method within a type)
def resolve(object:, **_rest)
root_instance = object.public_send(root)
Loaders::Association.for(
root_instance.class,
attachment_assoc => :blob
).load(root_instance)
end
# This method is called if the result of the `resolve`
# is a lazy value (e.g., a Promise like in our case)
def after_resolve(value:, **_rest)
if value.respond_to?(:map)
attachments = value.map { after_resolve_attachment(_1) }.compact
if options[:as] == :single
attachments.first
else
attachments
end
else
attachment = after_resolve_attachment(value)
if options[:as] == :multiple
[attachment].compact
else
attachment
end
end
end
private
def after_resolve_attachment(attachment)
return unless attachment
if attachment.virus_scanner.safe? || attachment.virus_scanner.pending?
attachment
end
end
end
end