Home > Back-end >  ActiveStorage - Could not find or build blob: expected attachable, got #<ActionDispatch::Http::Up
ActiveStorage - Could not find or build blob: expected attachable, got #<ActionDispatch::Http::Up

Time:01-02

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
  • Related