Grape Routing Error - No route matches for action for namespace + explanation

4.1k Views Asked by At

I have simple Rails application with Grape API Endpoint. I followed this tutorial so I set everything as it is there, just replaced hussars for users. I have troubles to make this working, because my routes seems to be corrupted. I have following folder structure:

├── app
│   ├── controllers
│   │   ├── api
│   │   │   ├── base.rb
│   │   │   └── v2
│   │   │       ├── api.rb
│   │   │       ├── defaults.rb
│   │   │       └── users.rb

base.rb

module API
  class Base < Grape::API
    mount API::V2::Api
  end
end

api.rb

module API
  module V2
    class Api < Grape::API
      mount API::V2::Users
    end
  end
end

users.rb

module API
  module V2
    class Users < Grape::API
      include API::V2::Defaults

      group :tests do
          get "/test_1" do
          { test: "all"}
        end
      end


        get "/hello" do
            User.all.to_json
        end

        get '/rt_count' do
          { rt_count: "current_user.rt_count" }
        end
    end
  end
end

and in my Defaults.rb I have following code:

module API
  module V2
    module Defaults
      extend ActiveSupport::Concern

      included do

        version 'v2', using: :path
        default_format :json
        format :json
        content_type :json, 'application/json'

        #formatter :json, Grape::Formatter::ActiveModelSerializers

        rescue_from Mongoid::Errors::DocumentNotFound do |e|
          error_response(message: e.message, status: 404)
        end
      end
    end
  end
end

routes.rb

Rails.application.routes.draw do

  mount API::Base => '/api'

Listing routes(using gem 'grape-rails-routes'):

                GET     /:version/tests/test_1(.:format)           API::V2::Users
                GET     /:version/hello(.:format)                  API::V2::Users
                GET     /:version/rt_count(.:format)               API::V2::Users
                OPTIONS /:version/tests/test_1(.:format)(.:format) API::V2::Users
                PUT     /:version/tests/test_1(.:format)(.:format) API::V2::Users
                POST    /:version/tests/test_1(.:format)(.:format) API::V2::Users
                DELETE  /:version/tests/test_1(.:format)(.:format) API::V2::Users
                PATCH   /:version/tests/test_1(.:format)(.:format) API::V2::Users
                OPTIONS /:version/hello(.:format)(.:format)        API::V2::Users
                PUT     /:version/hello(.:format)(.:format)        API::V2::Users
                POST    /:version/hello(.:format)(.:format)        API::V2::Users
                DELETE  /:version/hello(.:format)(.:format)        API::V2::Users
                PATCH   /:version/hello(.:format)(.:format)        API::V2::Users
                OPTIONS /:version/rt_count(.:format)(.:format)     API::V2::Users
                PUT     /:version/rt_count(.:format)(.:format)     API::V2::Users
                POST    /:version/rt_count(.:format)(.:format)     API::V2::Users
                DELETE  /:version/rt_count(.:format)(.:format)     API::V2::Users
                PATCH   /:version/rt_count(.:format)(.:format)     API::V2::Users
                GET     /:version/tests/test_1(.:format)           API::V2::Api
                GET     /:version/hello(.:format)                  API::V2::Api
                GET     /:version/rt_count(.:format)               API::V2::Api
                OPTIONS /:version/tests/test_1(.:format)(.:format) API::V2::Api
                PUT     /:version/tests/test_1(.:format)(.:format) API::V2::Api
                POST    /:version/tests/test_1(.:format)(.:format) API::V2::Api
                DELETE  /:version/tests/test_1(.:format)(.:format) API::V2::Api
                PATCH   /:version/tests/test_1(.:format)(.:format) API::V2::Api
                OPTIONS /:version/hello(.:format)(.:format)        API::V2::Api
                PUT     /:version/hello(.:format)(.:format)        API::V2::Api
                POST    /:version/hello(.:format)(.:format)        API::V2::Api
                DELETE  /:version/hello(.:format)(.:format)        API::V2::Api
                PATCH   /:version/hello(.:format)(.:format)        API::V2::Api
                OPTIONS /:version/rt_count(.:format)(.:format)     API::V2::Api
                PUT     /:version/rt_count(.:format)(.:format)     API::V2::Api
                POST    /:version/rt_count(.:format)(.:format)     API::V2::Api
                DELETE  /:version/rt_count(.:format)(.:format)     API::V2::Api
                PATCH   /:version/rt_count(.:format)(.:format)     API::V2::Api
                GET     /:version/tests/test_1(.:format)           API::Base
                GET     /:version/hello(.:format)                  API::Base
                GET     /:version/rt_count(.:format)               API::Base

First of all I'm kind of confused about the routes, which are generated out-of-the box from Grape. I have few questions:

  1. Why Grape lists twice the format for some APIs? (.:format)(.:format)
  2. Why I have two entries for most of the APIs? It seems to me like it's caused by code in file api.rb
  3. Bonus question: How do I turn off XML handling in Rails. I want to support just JSON

And now the funny stuff: When I call request:

  1. http://lclhost.com:3000/api/v2/hello.json - the API is working as expected
  2. http://lclhost.com:3000/api/v2/rt_count.json - the API is working as expected
  3. http://lclhost.com:3000/api/v2/tests/test_1.json - API is not working, returning No route matches [GET] "/api/v2/tests/test_1.json"

I'm most certain, that there is some small setup, or configuration in Grape namespace, which am I not able to find.

2

There are 2 best solutions below

1
On

I think this is because group is a parameter definition block, not a route block, change it to namespace.

0
On

Replace users.rb with this code

module API
  module V2
    class Users < Grape::API
      include API::V2::Defaults

      resource :tests do

        get "/test_1" do
          { test: "all"}
        end


        get "/hello" do
            { User.all.to_json }
        end

        get '/rt_count' do
          { rt_count: "current_user.rt_count" }
        end

       end

    end

  end

end