Router recognize

Hello, I have an app with this kind of routing:

# frozen_string_literal: true

require "hanami/middleware/body_parser"

module NextExaminer
  class Routes < Hanami::Routes
    slice :reviewer_admin, at: "/reviewer_admin" do
      use ReviewerAdmin::Authentication::App
      use Hanami::Middleware::BodyParser, :json

      scope "api" do
        post "/blocks/:block_id/questions", to: "questions.create"
      end
    end
  end
end

For this action, I am writing a request test on rspec:

    ...
    it "work..." do
      json_post "/reviewer_admin/api/blocks/#{block.id}/questions", data

      expect(last_response).to be_successful
    end

After tests, I have the rspec-openapi query analyser to generate openapi from actual queries.

The query analyser uses the function:

route = Hanami.app.router.recognize(request.path, method: request.method)

... route.routable?

In my case for these values:

irb:021> request.path
=> "/reviewer_admin/api/blocks/1/questions"
irb:022> request.method
=> "POST"

i have:

irb:023> route.routable?
=> false

I tried reproducing it in this simple case, but the problem does not occur.

irb:011* router = Hanami::Router.new do
irb:012*   scope "api" do
irb:013*     get "/books/:id/foo", to: ->(*) { }, as: :book
irb:014*   end
irb:015> end
=> 
#<Hanami::Router:0x00007f2061811b80
...
irb:016> route = router.recognize("/api/books/23/foo")
=> 
#<Hanami::Router::RecognizedRoute:0x00007f20619f6c20
...
irb:017> route.routable?
=> true

I tried running my application this way

      # use ReviewerAdmin::Authentication::App
      # use Hanami::Middleware::BodyParser, :json

But it didn’t affect anything, looks like a problem using slice in routing.
I’d be glad to get help in figuring out why route recognize doesn’t work in this case.

Try inspecting the route more instead of the request. Request method POST might not get parsed as you expect.

irb> route = app.router.recognize(Rack::MockRequest.env_for("/api/blocks/3/questions", method: :post))
=> #<Hanami::Router::RecognizedRoute:0x0000742c89b78638
  @endpoint=
    #<Proc:0x0000742c8a6b4830 .asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/hanami-2.1.0/lib/hanami/slice/routing/resolver.rb:73 (lambda)>,
    @env=
      irb> route.verb
=> "POST"
irb> route = app.router.recognize("/api/blocks/3/questions", method: "POST")
=> #<Hanami::Router::RecognizedRoute:0x0000742c89b24d58
  @endpoint=nil,
    @env=
      {"rack.version"=>[1, 3],
       "rack.input"=>#<StringIO:0x0000742c89b25168>,
         irb> route.verb
=> "GET"

Take note of route.verb inspection and @endpoint. routable? definition is just

def routable?
  !@endpoint.nil?
end

So I think this is the case of passing incomplete/incorrect data to your recognize. The example you tested on is much simpler than the one that is causing you problems.
Inspect params and the verb and the endpoint on the route before checking routable? It should lead you to what is the problem with passed arguments.

The recognize method lists a lot of examples that might clear some stuff out

Great, it worked!
Thank you for your help.

1 Like