Ruby on Rails 中的路由冲突问题

4

我正在使用Devise gem,并为用户创建了一个show页面。我的想法是创建一个简单的路径,如www.website.com/:id,并按照下面所示进行配置:

  devise_for :users, path: '', path_names: {sing_in: "login", sing_out: 
     "signout", sing_up: "signup", edit: "edit"}, 
     :controllers => {:registrations => :registrations }
  resources :users, only: [:show]
  get '/:id' => 'users#show', as: :profile

我的路由正常工作,但除了 show 页面外,我还有一些在 static controller 下的页面,例如 about 页面。我希望能够像这样访问它们:www.website.com/about,以下是我定义静态路由的方式:

get '/about', to: 'static#about'

现在,如果我试图重定向到关于页面,我会收到一个错误:

ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User with 'id'=about

这是我的users_controller.rb文件:
class UsersController < ApplicationController

  def show
    @user = User.find_by_id(params[:id])
    @services = @user.services
  end

  ...
end

我尝试搜索类似的错误,但没有找到类似的内容。请问有谁可以告诉我我做错了什么吗?
非常感谢您的帮助和时间。

4
你的路由 get '/about', to: 'static#about' 应该在 get '/:id' => 'users#show', as: :profile 路由之前定义。 - lightalloy
3
假设您期望用户调用中包含数字,而静态页面调用中包含字母,您可以使用约束条件:http://guides.rubyonrails.org/routing.html#specifying-constraints - Marek Lipka
1
@lightalloy 这是我的第一个想法,但它行不通,因为这真的是对静态页面控制器的调用,就像作者写的那样。 - Marek Lipka
@MarekLipka 谢谢您的回答。如果我想在其他页面上添加数字值(例如:www.website/123),是否有其他类似的解决方案? - Anton S.
路由从上到下进行匹配。@lightalloy的建议对你没有用吗?http://guides.rubyonrails.org/routing.html - inveterateliterate
@inveterateliterate,确实有问题,但我正在努力解决Marek Lipka指出的问题。 - Anton S.
1个回答

7
这里有两个要点:
  • 路由不了解参数类型
  • 路由从上到下匹配
在这种情况下,我怀疑你的单层路由被定义为 get '/:id' 路由。因此,该路由会捕获所有请求,即使是 /anything,因为路由认为 anything 是一个参数。
只需将路由定义移至任何其他 /about 等路由之下,以便它们首先匹配。
像这样:
get '/about', to: 'static#about'
get '/:id' => 'users#show', as: :profile

添加了一个代码示例,同时需要注意 @AnthonyBrooks ,您需要添加验证以防止用户具有与任何定义的路由相同的id / slug / name;这将防止用户感到沮丧(以防万一有人尝试将“about”作为他们的用户名;-)) - user9903
@RudolfOlah 哇,我没有想过...很好的观点!非常感谢! - Anton S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接