Steps to reproduce
Gems
gem 'graphql', '1.13.2'
gem 'apollo_upload_server', '2.1.0'
app/graphql/mutations/create_document.rb
module Mutations
class CreateDocument < Mutations::BaseMutation
description "Create a document"
argument :doc, ApolloUploadServer::Upload, required: true, description: "The document to upload"
field :document, Types::Objects::DocumentType, null: false
field :code, Types::Enums::CodeEnum, null: false
def resolve(doc:)
authenticate_user
document = context[:current_user].documents.build(doc: doc)
if document.save
{document: document, code: "SUCCESS"}
else
raise GraphQL::ExecutionError.new(document.errors.full_messages.join(", "), extensions: {code: "UNPROCESSABLE_ENTITY", errors: document.errors})
end
end
end
end
Query GraphQL Server
Processing by GraphqlController#execute as */*
17:34:47 web.1 |
17:34:47 web.1 | Variables:
17:34:47 web.1 | {"doc"=>
17:34:47 web.1 | #<ActionDispatch::Http::UploadedFile:0x0000ffff6c90ffd0
17:34:47 web.1 | @content_type="image/jpeg",
17:34:47 web.1 | @headers=
17:34:47 web.1 | "Content-Disposition: form-data; name=\"0\"; filename=\"www.abcd.jpg\"\r\n"
17:34:47 web.1 | "Content-Type: image/jpeg\r\n",
17:34:47 web.1 | @original_filename="www.YTS.MX.jpg",
17:34:47 web.1 | @tempfile=#<File:/tmp/RackMultipart20220101-9-dn78ar.jpg>>}
17:34:47 web.1 |
17:34:47 web.1 | Query:
17:34:47 web.1 | mutation createDocument($doc: Upload!){createDocument(input: {doc: $doc}){document{url}}}
app/models/document.rb
class Document < ApplicationRecord
## RELATIONSHIPS
has_one_attached :doc
belongs_to :documentable, polymorphic: true, optional: true
belongs_to :user, optional: true
## VALIDATIONS
validate :doc_presence, on: :create
def doc_presence
pattern = %r{^(image|application|text)/(.) $}
unless doc.attached? && pattern.match?(doc.attachment.blob.content_type)
errors.add(:doc, I18n.t("errors.models.document.file_presence"))
end
end
end
Postman URL: POST http://localhost:3000/graphql form-data
"operations" = {"query":"mutation createDocument($doc: Upload!){createDocument(input: {doc: $doc}){document{url}}}", "variables": { "doc": null }}
"map" = { "0": ["variables.doc"]}
"0" = FILE_TO_BE_UPLOADED
spec/graphql/mutations/create_document_spec.rb
require 'rails_helper'
module Mutations
RSpec.describe CreateDocument, type: :request do
describe '.resolve' do
let(:session) {FactoryBot.create(:session)}
it 'create a document for the user' do
session.user.confirm
headers = sign_in_test_headers session
params = FactoryBot.attributes_for(:document, :with_image, user_id: session.user_id)
query = <<-GRAPHQL
mutation ($input: CreateDocumentInput!) {
createDocument(input: $input) {
document {
id
url
}
}
}
GRAPHQL
file = fixture_file_upload("spec/support/fixtures/image.png")
variables = {input: {doc: ::ApolloUploadServer::Wrappers::UploadedFile.new(fixture_file_upload("spec/support/fixtures/image.png"))}}
response = ApiSchema.execute(query, variables: variables, context: {current_user: session.user})
end
end
end
end
Expected behavior
File should get attached
Actual behavior
Could not find or build blob: expected attachable, got #<ActionDispatch::Http::UploadedFile:0x0000ffff6c90ffd0 @tempfile=#<Tempfile:/tmp/RackMultipart20220101-9-dn78ar.jpg>, @original_filename="www.abcd.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"0\"; filename=\"www.abcd.jpg\"\r\nContent-Type: image/jpeg\r\n">
ArgumentError:
Could not find or build blob: expected attachable, got #<Rack::Test::UploadedFile:0x0000aaaafe8ba7a0 @original_filename="image.png", @tempfile=#<Tempfile:/tmp/image20220101-1-c5c4q4.png>, @content_type=nil>
# /usr/local/bundle/gems/activestorage-7.0.0/lib/active_storage/attached/changes/create_one.rb:74:in `find_or_build_blob'
# /usr/local/bundle/gems/activestorage-7.0.0/lib/active_storage/attached/changes/create_one.rb:20:in `blob'
# /usr/local/bundle/gems/activestorage-7.0.0/lib/active_storage/attached/changes/create_one.rb:12:in `initialize'
# /usr/local/bundle/gems/activestorage-7.0.0/lib/active_storage/attached/model.rb:65:in `new'
# /usr/local/bundle/gems/activestorage-7.0.0/lib/active_storage/attached/model.rb:65:in `doc='
# /usr/local/bundle/gems/enumerize-2.5.0/lib/enumerize/base.rb:53:in `initialize'
# ./app/graphql/mutations/create_document.rb:13:in `resolve'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/resolver.rb:107:in `public_send'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/resolver.rb:107:in `block (3 levels) in resolve_with_support'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema.rb:118:in `after_lazy'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/resolver.rb:95:in `block (2 levels) in resolve_with_support'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema.rb:118:in `after_lazy'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/resolver.rb:86:in `block in resolve_with_support'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema.rb:118:in `after_lazy'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/resolver.rb:75:in `resolve_with_support'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/relay_classic_mutation.rb:64:in `resolve_with_support'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/field.rb:812:in `public_send'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/field.rb:812:in `block in public_send_field'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/field.rb:848:in `with_extensions'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/field.rb:794:in `public_send_field'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/field.rb:708:in `block in resolve'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema.rb:118:in `after_lazy'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/field.rb:706:in `resolve'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/execution/interpreter/runtime.rb:510:in `block (4 levels) in evaluate_selection_with_args'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/tracing.rb:66:in `trace'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/execution/interpreter/runtime.rb:509:in `block (3 levels) in evaluate_selection_with_args'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/query.rb:366:in `block in with_error_handling'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/execution/errors.rb:107:in `with_error_handling'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/query.rb:365:in `with_error_handling'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/execution/interpreter/runtime.rb:508:in `block (2 levels) in evaluate_selection_with_args'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/execution/interpreter/runtime.rb:796:in `resolve_with_directives'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/execution/interpreter/runtime.rb:505:in `block in evaluate_selection_with_args'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/execution/interpreter/runtime.rb:899:in `after_lazy'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/execution/interpreter/runtime.rb:439:in `evaluate_selection_with_args'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/execution/interpreter/runtime.rb:431:in `block in evaluate_selection'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/schema/member/has_arguments.rb:204:in `block (3 levels) in coerce_arguments'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/dataloader.rb:181:in `block in run'
# /usr/local/bundle/gems/graphql-1.13.2/lib/graphql/dataloader.rb:303:in `block in spawn_fiber'
System configuration
Rails version: 7.0.0
Ruby version: 3.0.3
CodePudding user response:
First you need to create blob file in case of active storage.
def attach_doc(doc_param)
doc = ActiveStorage::Blob.create_after_upload!(
io: doc_param,
filename: doc_param.original_filename,
content_type: doc_param.content_type
)
document = context[:current_user].documents.doc.attach(doc)
end