Ruby on rails 基于条件的铁路线路

Ruby on rails 基于条件的铁路线路,ruby-on-rails,ruby-on-rails-3,routes,ruby-on-rails-3.2,rails-routing,Ruby On Rails,Ruby On Rails 3,Routes,Ruby On Rails 3.2,Rails Routing,我有三个角色:讲师、学生、管理员,每个角色都有带“主”视图的控制器 所以这个很好用 get "instructor/home", :to => "instructor#home" get "student/home", :to => "student#home" get "admin/home", :to => "admin#home" 我想写一个像下面这样的虚荣url,它将根据用户id的角色路由到正确的主页 get "/:user_id/home", :to => "

我有三个角色:讲师、学生、管理员,每个角色都有带“主”视图的控制器

所以这个很好用

get "instructor/home", :to => "instructor#home"
get "student/home", :to => "student#home"
get "admin/home", :to => "admin#home"
我想写一个像下面这样的虚荣url,它将根据
用户id
的角色路由到正确的主页

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

如何完成此操作?

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

您需要的是一个控制器方法,它可以加载所需的任何数据,可能是用户记录,并使用
redirect\u相应地重定向到

这是一件相当标准的事情

更新:

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

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
class HomeController“讲师之家”)
结束
def学生之家
# ...
呈现(:模板=>'student\u home')
结束
def管理员之家
# ...
呈现(:模板=>'admin\u home')
结束
结束

我提供了另一种方法,因为在Rails中搜索基于角色的路由时,这个SO问题几乎出现在顶部

我最近需要实现一些类似的东西,但希望避免控制器中有大量的条件-这一点由于我的每个用户角色都需要加载和显示完全不同的数据而变得更加复杂。我选择通过使用

上述代码最重要的部分是
匹配?
方法,该方法将确定路线是否匹配。该方法被传递给
request
对象,该对象包含有关所做请求的各种信息。在我的例子中,我正在查找会话cookie中存储的
:user\u 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
发出请求的管理员将被路由到
管理员控制器的home操作,向
/home
发出请求的讲师将被路由到
讲师控制器的home操作,向
/home
发出请求的学生将被路由到
学生控制器的home操作

更多信息
如果您想了解更多信息,我最近在上写了关于此方法的文章。

可能更简单的方法是使用一个“全面”控制器,根据用户类型将用户重定向到适当的控制器/操作对。我正在考虑实现一个名为“user\u redirect”的控制器方法,并使用redirect实现此方法。我的目标是在他们登录后立即显示一个虚荣url。我能做到吗?您希望浏览器中的URL就是这样吗?如果是这样,你需要在内部做一些事情来隐藏它。这通常涉及一个控制器,该控制器可以呈现多个不同模板中的一个,或者是一个带有条件节或条件加载部分的标准模板。是的,我希望浏览器中的URL就是这样。你能详细说明一下吗?谢谢使用相同的URL意味着必须执行相同的控制器操作,这反过来意味着该操作需要能够处理所有不同的用例。请记住,您可以在控制器中使用
render(:template=>“…”)
渲染不同的模板。请看修改后的答案。你不能这样做=/=我不知道怎么做。肯定是比被接受的答案更好的答案。它帮助我解决了一个稍微不那么复杂的问题,但这是一个无法通过控制器中的逻辑实现的问题。谢谢非常感谢。在routes.rb中有条件重定向要好得多。很好的答案,我阅读并学习了很多关于约束的知识!我知道这样的事情是可能的,我讨厌在我有所有需要的数据时做重定向。有了这个请求,我就有了用户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