Skip to content

Rails 7 router can raise NoMethodError (undefined method names' for nil:NilClass)` #47244

@engwan

Description

@engwan

Steps to reproduce

When having a route with a regex constraint with a negative lookahead, we get exceptions when matching some routes.

I simplified the regex and created a minimal example below:

# frozen_string_literal: true

require "bundler/inline"

gemfile(true) do
  source "https://rubygems.org"

  git_source(:github) { |repo| "https://github.com/#{repo}.git" }

  # Activate the gem you are reporting the issue against.
  gem "rails", "~> 7.0.0"
end

require "rack/test"
require "action_controller/railtie"

class TestApp < Rails::Application
  config.root = __dir__
  config.hosts << "example.org"
  config.session_store :cookie_store, key: "cookie_store_key"
  secrets.secret_key_base = "secret_key_base"

  config.logger = Logger.new($stdout)
  Rails.logger  = config.logger

  routes.draw do
    get '*namespace_id/:project_id/bar', to: 'test#index', constraints: { namespace_id: /(?!api\/)[a-zA-Z0-9_\\]+/, project_id: /[a-zA-Z0-9]+/ }

    # This version works:
    #get '*namespace_id/:project_id/bar', to: 'test#index', constraints: lambda { |req| req.params[:namespace_id].match?(/\A(?!api\/)[a-zA-Z0-9_\\]+\z/) && req.params[:project_id].match?(/\A[a-zA-Z0-9]+\z/) }

    get '/api/foo/bar', to: 'test#index'
  end
end

class TestController < ActionController::Base
  include Rails.application.routes.url_helpers

  def index
    render plain: "Home"
  end
end

require "minitest/autorun"

class BugTest < Minitest::Test
  include Rack::Test::Methods

  def test_returns_success
    get "/api/foo/bar"
    assert last_response.ok?
  end

  private
    def app
      Rails.application
    end
end

Expected behavior

It should match the second route and render the page

Actual behavior

It raises an exception:

Started GET "/api/foo/bar/" for 127.0.0.1 at 2023-02-03 14:04:19 +0800

NoMethodError (undefined method `names' for nil:NilClass):

actionpack (7.0.4.2) lib/action_dispatch/journey/router.rb:126:in `block in find_routes'
actionpack (7.0.4.2) lib/action_dispatch/journey/router.rb:123:in `map!'
actionpack (7.0.4.2) lib/action_dispatch/journey/router.rb:123:in `find_routes'
actionpack (7.0.4.2) lib/action_dispatch/journey/router.rb:32:in `serve'
actionpack (7.0.4.2) lib/action_dispatch/routing/route_set.rb:852:in `call'

System configuration

Rails version: 7.0.4.2

Ruby version: 3.0.5

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions