tutorial rails learn create crear beginner ruby-on-rails ruby-on-rails-3 routes ruby-on-rails-3.2 rails-routing

ruby-on-rails - learn - ruby on rails pdf



Rutas de carriles basadas en condiciĆ³n (2)

Tengo tres roles: Instructor, Estudiante, Administrador y cada uno tiene controladores con una vista de "inicio".

así que esto funciona bien,

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

Quiero escribir una URL de vanidad como la de abajo, que se enrutará según la función del user_id de user_id a la página de inicio correcta.

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

¿Cómo logro esto?


Estoy proporcionando un enfoque alternativo a medida que esta pregunta de SO se acerca a la cima cuando se busca el enrutamiento basado en roles en Rails.

Hace poco tuve que implementar algo similar, pero quería evitar tener una gran cantidad de condicionales en el controlador; esto se vio agravado por el hecho de que cada uno de mis roles de usuario requería que se cargaran y presentaran datos completamente diferentes. Opté por mover la lógica decisiva a la capa de enrutamiento utilizando una Restricción de enrutamiento .

# 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

¿La parte más importante del código anterior son las matches? Método que determinará si la ruta coincidirá o no. Al método se le pasa el objeto de request que contiene información diversa sobre la solicitud que se está realizando. En mi caso, estoy buscando el :user_id almacenado en la cookie de sesión y lo uso para encontrar al usuario que realiza la solicitud.

A continuación, puede utilizar esta restricción al definir sus rutas.

# 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

Con lo anterior en su lugar, un administrador que realice una solicitud a /home se enrutará a la acción de inicio del AdministratorsController de AdministratorsController , un instructor que haga una solicitud a /home se enrutará a la acción de inicio del Control de InstructorsController , y un estudiante que haga una solicitud a /home sería enrutado a la acción de home del StudentsController .

Más información

Si está buscando más información, recientemente escribí sobre este enfoque en mi blog .


No puede hacer esto con rutas porque el sistema de enrutamiento no tiene la información necesaria para tomar esta decisión. All Rails sabe que en este punto de la solicitud es lo que son los parámetros y no tiene acceso a nada en la base de datos.

Lo que necesita es un método de controlador que pueda cargar cualquier dato que se requiera, presumiblemente el registro del usuario y redireccione en consecuencia usando redirect_to .

Esto es una cosa bastante estándar para hacer.

Actualizar:

Para realizar todo esto dentro de una única acción del controlador, deberá dividir su lógica de acuerdo con el rol. Un ejemplo es:

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