Percorsi di rotaie in base alle condizioni

Ho tre ruoli: Instuctor, Student, Admin e ognuno ha controller con una vista “home”.

quindi questo funziona bene,

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

Voglio scrivere un url di vanità come di seguito che verrà instradato in base al ruolo di user_id alla home page corretta.

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

Come posso realizzare questo?

Non è ansible farlo con rotte perché il sistema di routing non ha le informazioni necessarie per prendere questa decisione. Tutti i binari sanno a questo punto della richiesta quali sono i parametri e non hanno accesso a nulla nel database.

Quello di cui hai bisogno è un metodo di controllo in grado di caricare qualsiasi dato richiesto, presumibilmente il record dell’utente, e redirect di conseguenza usando redirect_to .

Questa è una cosa abbastanza normale da fare.

Aggiornare:

Per eseguire tutto questo all’interno di un’azione a controller singolo è necessario suddividere la logica in base al ruolo. Un esempio è:

 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 

Sto fornendo un approccio alternativo in quanto questa domanda SO si avvicina ai vertici quando si cerca il routing basato sui ruoli in Rails.

Recentemente ho avuto bisogno di implementare qualcosa di simile ma volevo evitare di avere un gran numero di condizionali nel controller – questo era aggravato dal fatto che ognuno dei miei ruoli utente richiedeva dati completamente diversi da caricare e presentare. Ho optato per spostare la logica decisionale sul livello di routing utilizzando un vincolo di instradamento .

 # 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 più importante del codice sopra è le matches? metodo che determinerà se la rotta corrisponderà o meno. Il metodo viene passato all’object request che contiene varie informazioni sulla richiesta effettuata. Nel mio caso, sto cercando il :user_id memorizzato nel cookie di sessione e usando quello per trovare l’utente che effettua la richiesta.

È quindi ansible utilizzare questo vincolo quando si definiscono i percorsi.

 # 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 quanto sopra posto, un amministratore che effettua una richiesta a /home verrebbe indirizzato all’azione home di AdministratorsController , un istruttore che effettua una richiesta a /home verrebbe indirizzato all’azione home di InstructorsController e uno studente che inoltra una richiesta a /home verrebbe indirizzato all’azione home di StudentsController .

Maggiori informazioni

Se stai cercando ulteriori informazioni, di recente ho scritto di questo approccio sul mio blog .