Grape: Inherit from Grape::API::Instance breaks Boolean type

Created on 3 Jul 2019  路  11Comments  路  Source: ruby-grape/grape

Recently I followed the UPGRADING.md guide to upgrade Grape from 1.0.3 to 1.2.4 and an error occurs due to the use of type: Boolean in params block.
This happens only when inheriting from Grape::API::Instance. I wrote a small rack app to test and the behaviour is the same.

# config.ru
require 'grape'

module App
  class API < Grape::API::Instance
    resource :system do
      params do
        optional :hit, type: Boolean
      end
      get :ping do
        "pong"
      end
    end
  end
end

run App::API

Error:

NameError: uninitialized constant App::API::Boolean

I could easily change the Boolean to Virtus::Attribute::Boolean to fix this issue on my app but since you already supported this Boolean type feature, I think it should be supported in the next releases too.

Thank you.

bug?

Most helpful comment

The problem stems from the fact that an undocumented breaking change from the upgrade is that Class.new(Grape::API) is no longer a proper Rack application, rather Class.new(Grape::API::Instance) is, this has very few real life implications but I'll see whether I can make it so that Class.new(Grape::API) is also a Rack app
Else, I'll add this to the breaking changes. Thanks for bringing this up :+1:

All 11 comments

Feel free to PR a fix to this effect. I would also try to track where this got removed. There's probably a good reason since Boolean is not a native type in Ruby.

Note: if you are just creating an API you should not be inheriting from ::Instance rather just from Grape::API

In the Upgrading.md guide the reference to when you should use Grape::API::Instance it is only when you are monkeypatching the class (which is not what you are doing here)

i.e. on this example you should be doing:

# config.ru
require 'grape'

module App
  class API < Grape::API
    resource :system do
      params do
        optional :hit, type: Boolean
      end
      get :ping do
        "pong"
      end
    end
  end
end

run App::API

Thank you @myxoh for pointing that out. As I can see, the inheritance from Grape::API works great for a rack app.

However, on my app where I integrate grape with rails and using rspec together with rack-test, when I run the api specs, it returns 404 if it inherits from Grape::API. Notice that the APIs still works normally when running on a real server. Since I want to make sure the tests pass before deployment, I just let them inherit from Grape::API::Instance 馃槃 . That's where I encounter the Boolean problem.

FYI, my app's APIs structure would look similar to this.

Rails.application.routes.draw do
  mount API::Base, at: "/"
end
# app/controllers/api/base.rb

class API::Base < Grape::API
  mount API::V1::Base
end
# app/controllers/api/v1/base.rb

class API::V1::Base < Grape::API
  version 'v1', using: :path
  format :json

  mount API::V1::Ping
end
# app/controllers/api/v1/ping.rb

class API::V1::Ping < Grape::API
  resource :system do
    params do
      optional :hit, type: Boolean
    end
    get :ping do
      "pong"
    end
  end
end

Edited: Add failing spec

# spec/requests/api/v1/ping.rb

require 'rails_helper'
require 'rack/test'

describe API::V1 do
  include Rack::Test::Methods

  def app
    API::V1::Ping
  end

  it 'returns pong' do
    get '/v1/system/ping'
    expect(last_response.status).to be(200)
  end
end

Interesting as this is a similar setup to the one I've got. Could you please attach the failing spec too? I'll look into this!

Thanks !

Oops! I should have attached it in the first place. I edited the above comment and added the failing spec.

Thanks!

This is interesting, and sounds like a bug.
Just as a colour point, if you replace the

def app
   API::V1::Ping
 end

With

def app
  Rails.application
end

The spec will go green again.

The problem stems from the fact that an undocumented breaking change from the upgrade is that Class.new(Grape::API) is no longer a proper Rack application, rather Class.new(Grape::API::Instance) is, this has very few real life implications but I'll see whether I can make it so that Class.new(Grape::API) is also a Rack app
Else, I'll add this to the breaking changes. Thanks for bringing this up :+1:

I think we could use an integration test in Grape.

I upgraded https://github.com/ruby-grape/grape-on-rails/pull/8 and it "just worked". This is because I don't have def app, that is not required for Rails, only to declare a Rack app in tests if you're using Rack::Test?

OK, I've actually managed to replicate the issue on a spec in the rack integration, and also find a solution ( I believe)
I'll create a PR

I think this issue can now be closed, could you confirm @sondnm whether you can now get your spec to work by inheriting from Grape::API ?

It is working great now! Thanks a lot @myxoh.

Since the Boolean type for Grape::API::Instance is not relevant anymore, I will close this issue.

Was this page helpful?
0 / 5 - 0 ratings