demarches-normaliennes/app/graphql/extensions/attachment.rb

66 lines
1.9 KiB
Ruby
Raw Normal View History

2018-11-20 22:27:40 +01:00
# 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
2018-11-20 22:27:40 +01:00
def apply
# Here we try to define the ActiveRecord association name:
2018-11-20 22:27:40 +01:00
# - 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
2018-11-20 22:27:40 +01:00
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)
2018-11-20 22:27:40 +01:00
Loaders::Association.for(
root_instance.class,
2018-11-20 22:27:40 +01:00
attachment_assoc => :blob
).load(root_instance)
2018-11-20 22:27:40 +01:00
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
2019-12-11 12:24:50 +01:00
end
2018-11-20 22:27:40 +01:00
end
end
end