Rails 路由可选段映射问题

Rails route optional segments mapping issue

我原来有这样定义的路由:

get ':foo(/:bar)/:baz(/:qux)/:slug', to: 'application#show', constraints: { baz: /.+?\-\d+/ }, as: test

使用此配置,如果我在我的路径中省略 :bar 它工作正常: foo/baz-123/qux-quux/test

控制器returns参数如下:{foo: 'foo', baz: 'baz-123', qux: 'qux-quux', slug: 'test'}

现在,规范发生了变化,我需要在 baz 约束中接受字母数字字符,所以我这样做了:

get ':foo(/:bar)/:baz(/:qux)/:slug', to: 'application#show', constraints: { baz: /.+?\-[a-z0-9]+/ }, as: test

使用此配置,参数映射开始表现不同。同样路径foo/baz-123/qux-quux/test returns控制器中的参数如下:

{foo: 'foo', bar: 'baz-123', baz: 'qux-quux', slug: 'test'}

我认为它正在发生,因为 qux-quux 也匹配约束,所以我将其更改为 /.+?\-(?=.*\d+)[a-z0-9]+/ 以确保 :baz 参数在第二部分至少需要一位数字在 -.

之后

然而,即使 qux-quxx 不匹配约束,控制器仍然 returns 相同的错误映射。

在多个可选段的情况下,Rails如何映射参数?

您的路由路径 :foo(/:bar)/:baz(/:qux)/:slug 包含 5 个段、3 个强制段和 2 个可选段,因此请求路径将被验证当且仅当:

  • 它包含足够的 5 个片段
  • 它包含 3 个部分,在这种情况下,显然是 3 个必填部分
  • 它包含 4 个片段,这里有 2 个有效案例::foo/:bar/:baz/:slug:foo/:baz/:qux/:slug

当您为段设置约束时,匹配器将检查该段是否与约束匹配。正如您在前 2 种情况下看到的那样,匹配器知道段 :baz 在哪里,但是在 4 个段的情况下,匹配器必须选择 2 个有效情况之一,所以它会混淆,因此它将检查段 1一个,然后选择最后一个匹配的。

/.+?\-[a-z0-9]+/ =~ "baz-123" # matched
/.+?\-[a-z0-9]+/ =~ "qux-quux" # matched <-- the last one

{foo: 'foo', bar: 'baz-123', baz: 'qux-quux', slug: 'test'}

我猜约束段设置的优先级高于其他段,因此首先检查它们,然后根据约束段位置检查其他段,在您的情况下,在验证段 :baz 之后,其左侧的段将是 :bar:slug 段在右侧(可选段 :qux 将被忽略)。

当您将约束更改为 /.+?\-(?=.*\d+)[a-z0-9]+/

/.+?\-(?=.*\d+)[a-z0-9]+/ =~ "baz-123" # matched <-- baz
/.+?\-(?=.*\d+)[a-z0-9]+/ =~ "qux-quux" # not matched

# so the params should be (the `:bar` will be ignored)
{foo: 'foo', baz: 'baz-123', qux: 'qux-quux', slug: 'test'}

在我看来,如果 :bar:baz 之间有任何不同的模式,最好也为段 :bar 设置约束,这样匹配器将一一检查不会再迷茫了。

get ':foo(/:bar)/:baz(/:qux)/:slug', to: 'application#show', constraints: { 
 bar: /.*/,
 baz: /.+?\-(?=.*\d+)[a-z0-9]+/ 
}, as: test

另一种方法,我认为,您可以设置段的默认值 :bar,并且在您的控制器中您可以处理该默认值,所以现在匹配器不会混淆。

还有一件事,你的最后一个正则表达式 /.+?\-(?=.*\d+)[a-z0-9]+/greedy,这将吞没所有路径而不考虑启动 /,因此路径 foo/bar/baz-x/test 将失败但是路径 foo/bar/baz-x/x1x 将通过,因为字符 - 后面有一个数字。您可以将贪婪部分 (?=.*\d+) 替换为 (?=[^\/]*\d+) 来修复它。所以要小心正则表达式约束。