Rails路由基于条件

我有三个角色:Instuctor,Student,Admin,每个角色都有一个带有“home”视图的控制器。

所以这很好,

get "instructor/home", :to => "instructor#home" get "student/home", :to => "student#home" get "admin/home", :to => "admin#home" 

我想写一个类似于下面的虚荣url,它会根据user_id的角色路由到正确的主页。

 get "/:user_id/home", :to => "instructor#home" or "student#home" or "admin#home" 

我该如何做到这一点?

您不能对路由执行此操作,因为路由系统没有做出此决定所需的信息。 所有Rails在此时都知道请求是参数是什么,并且不能访问数据库中的任何内容。

您需要的是一种控制器方法,可以加载所需的任何数据,可能是用户记录,并使用redirect_to相应的redirect_to

这是一个相当标准的事情。

更新:

要在单个控制器操作中执行所有这些操作,您需要根据角色拆分逻辑。 一个例子是:

 class HomeController < ApplicationController def home case when @user.student? student_home when @user.admin? admin_home when @user.instructor instructor_home else # Unknown user type? Render error or use a default. end end protected def instructor_home # ... render(:template => 'instructor_home') end def student_home # ... render(:template => 'student_home') end def admin_home # ... render(:template => 'admin_home') end end 

我正在提供一种替代方法,因为当在Rails中搜索基于角色的路由时,这个问题出现在顶部附近。

我最近需要实现类似的东西,但希望避免在控制器中有大量的条件 – 由于我的每个用户角色都需要加载和呈现完全不同的数据这一事实。 我选择使用路由约束将决策逻辑移动到路由层。

 # app/constraints/role_route_constraint.rb class RoleRouteConstraint def initialize(&block) @block = block || lambda { |user| true } end def matches?(request) user = current_user(request) user.present? && @block.call(user) end def current_user(request) User.find_by_id(request.session[:user_id]) end end 

上面代码中最重要的部分是matches? 确定路线是否匹配的方法。 该方法传递给request对象,该对象包含有关正在进行的请求的各种信息。 在我的情况下,我正在查找存储在会话cookie中的:user_id ,并使用它来查找发出请求的用户。

然后,您可以在定义路线时使用此约束。

 # config/routes.rb Rails.application.routes.draw do get 'home', to: 'administrators#home', constraints: RoleRouteConstraint.new { |user| user.admin? } get 'home', to: 'instructors#home', constraints: RoleRouteConstraint.new { |user| user.instructor? } get 'home', to: 'students#home', constraints: RoleRouteConstraint.new { |user| user.student? } end 

完成上述操作后,向/home发出请求的管理员将被路由到AdministratorsController的主动作,向/home发出请求的教师将被路由到InstructorsController主动作,并且学生发出请求/home将被路由到StudentsController主页操作。

更多信息

如果您正在寻找更多信息,我最近在我的博客上写了这个方法。