sel
sel

Reputation: 169

Upload document using grape api | ArgumentError (missing keyword: io)

I am trying to upload image using grape api. I have done the following steps.

  1. rails active_storage:install
  2. rails g model user name email avatar:attachment
  3. rails db:migrate
module API
  module V1
    class Users < Grape::API
      include API::V1::Defaults
      desc 'Create User'
      params do
        requires :name, type: String, desc: "User name"
        requires :email, type: String, desc: "User email"
        requires :avatar, :type => Rack::Multipart::UploadedFile, :desc => "Image file."
      end
      put "/user" do
        binding.pry
        User.create(params)
        return {status: 'success'}
      end
    end
  end
end

But I am getting the following error,

ArgumentError: missing keyword: io
from /Users/nnnn/.rbenv/versions/2.6.0/lib/ruby/gems/2.6.0/gems/activestorage-6.1.4/app/models/active_storage/blob.rb:97:in `build_after_unfurling'

Help me to fix this issue. curl command to hit the server.

[![curl --location --request PUT 'localhost:3000/api/v1/user' \ --header 'Cookie: __profilin=p%3Dt' \ --form 'avatar=@"/Users/nnnn/Downloads/1623340316453.jpeg"' \ --form 'name="Tester"' \ --form 'email="[email protected]"'][1]][1]

enter image description here

Upvotes: 3

Views: 736

Answers (1)

Martin M
Martin M

Reputation: 8668

When sending files to grape, grape fills the parameter with a HashWithIndifferentAccess.
for example, I have a picture1 that is:

0> params[:picture1]
=> {"filename"=>"haesel.jpg", "type"=>"image/jpeg", "name"=>"picture1", "tempfile"=>#<Tempfile:/var/folders/k7/cdl9fvt94j94_wdn6dr1jy6m0000gn/T/RackMultipart20231207-77241-9s9oot.jpg>, "head"=>"Content-Disposition: form-data; name=\"picture1\"; filename=\"haesel.jpg\"\r\nContent-Type: image/jpeg\r\n"}

0> params[:picture1].class
=> ActiveSupport::HashWithIndifferentAccess

ActiveStorage (as well as Paperclip, Carrierwaver etc.) expect an ActionDispatch::Http::UploadedFile. This UploadedFile has the expected IO.

It's easy to convert. In your example (by the way: create objects with POST to plural url (REST)):

module API
  module V1
    class Users < Grape::API
      include API::V1::Defaults
      desc 'Create User'
      params do
        requires :name, type: String, desc: "User name"
        requires :email, type: String, desc: "User email"
        requires :avatar, type: File, :desc => "Image file."
      end
      post '/users' do
        params[:avatar] = ActionDispatch::Http::UploadedFile.new params[:avatar]
        # binding.pry
        if User.create params
          status :created # 201 created
        else
          status :unprocessable_entity
        end
      end
    end
  end
end

Upvotes: 2

Related Questions