How to do POST request to Grape REST API using params block compatible with Swagger

2.6k views Asked by At

I am using grape to build a REST API, I am having some trouble with params options.

This is how I do a POST request:

# Curl Request
# curl -X POST -H "Content-Type:application/json" 0:9292/v1/articles -d '{"title":"hello","body":"world"}'
# {"error":"article is missing"}
# curl -X POST -H "Content-Type:application/json" 0:9292/v1/articles -d '{"article":{title":"hello","body":"world"}}'
# {"error":"article is invalid"}

As you can see if I omit article it fails article missing, If i put article and it fails article invalid.

This is the code, I am using grape-entity.

# Entity
module API
  module Entities
   class Article < Grape::Entity
    expose :title, documentation: { type: 'string', desc: 'Title' }
    expose :body, documentation: { type: 'string', desc: 'Body' }
   end
  end
end


# API
desc "Create an article"
params do
  requires :article, type: API::Entities::Article, documentation: { eg: "aklsdfj" }
end
post '/articles' do
  puts params
  article = Article.create(params(:title, :body))
  represent(article, env)
end


# Add Swagger Docs
add_swagger_documentation mount_path: 'api/doc',
api_version: 'v1',
markdown: GrapeSwagger::Markdown::KramdownAdapter,
hide_documentation_path: true,
base_path: Application.config.base_path,
    models: [API::Entities::Article]

Specifically the problem is caused by params block, it requires an :article of type API:Entities::Article.

Also note that, I am using add-swagger-documentation, and this code produces correct swagger documentation, so the solution have to be fully compatible with swagger. What is the correct usage of params block without offending the swagger.

1

There are 1 answers

2
Marlon On

I'm not sure what you're trying to accomplish here. I guess you want to change your post method in a way that it accepts a JSON like this:

{ attribute1: value, attribute2: value }

instead of

{ article: { attribute1: value, attribute2: value } }

In this case, you have to change your params block to something like this

params do
  requires :attribute1, type: String, documentation: { eg: "aklsdfj" }
  requires :attribute2, type: String, documentation: { eg: "aklsdfj" }
end

instead of

params do
    requires :article, type: API::Entities::Article, documentation: { eg: "aklsdfj" }
end

The params block above is expecting a JSON containing an article attribute composed by every attribute defined in the entity API::Entities::Article.

In fact, Grape doesn't accept entity objects as a type for a parameter.