2011-01-20 14 views
22

Sto lavorando a un'app di gestione del progetto e nell'app ho project_managers e clienti. Sto usando Devise e CanCan per l'autenticazione/autorizzazione.Come posso reindirizzare il percorso home dell'utente (root) in base al loro ruolo utilizzando Devise?

A che punto dopo l'accesso devo reindirizzare l'utente al proprio controller/layout/viste specifico? C'è un modo per verificare current_user.role in routes.rb e impostare il root (o il reindirizzamento) in base al fatto che siano o meno un project manager o un client? Questo è un cambiamento che posso apportare a Devise da qualche parte?

Grazie in anticipo per qualsiasi aiuto! --Mark

+0

Ho fatto una domanda simile: http://stackoverflow.com/questions/3799393/rails-routes-root-with-nested-resource - la risposta era quella di creare un controller separato per la home page che esegue il routing. Non è possibile accedere a tali informazioni Devise all'interno di routes.rb. – Skilldrick

risposta

32

Il file routes.rb non ha alcuna idea del ruolo dell'utente, quindi non sarà possibile utilizzarlo per assegnare percorsi root specifici.

Ciò che si può fare è configurare un controller (ad esempio, passthrough_controller.rb) che a sua volta può leggere il ruolo e il reindirizzamento. Qualcosa di simile a questo:

# passthrough_controller.rb 
class PassthroughController < ApplicationController 
    def index 
    path = case current_user.role 
     when 'project_manager' 
     some_path 
     when 'client' 
     some_other_path 
     else 
     # If you want to raise an exception or have a default root for users without roles 
    end 

    redirect_to path  
    end 
end 

# routes.rb 
root :to => 'passthrough#index' 

In questo modo, tutti gli utenti avranno un punto di entrata, che a sua volta li reindirizza al appropriata del controller/azione a seconda del loro ruolo.

+0

Grazie amico, questo ha funzionato completamente. – Mark

+2

http://stackoverflow.com/questions/4753871/how-can-i-redirect-a-users-home-root-path-based-on-their-role-using-devise/4754097#4754097 è una migliore implementazione , in quanto non crea un nuovo controller solo per il reindirizzamento. Inoltre, ciò comporterebbe 1 giro di andata e ritorno da browser a server ogni volta che un utente viene reindirizzato a root_path –

+0

Soluzione elegante che non richiede di modificare alcun codice esistente, cioè posso mantenere tutte le istruzioni 'redirect_to root_path' come erano prima. Mi piace :) – Wolfgang

6

Lo faccio in un'applicazione Rails 3 che utilizza Warden. Poiché Devise è costruito su Warden, penso che funzionerà per te, ma assicurati di sperimentarlo un po 'prima di fare affidamento su di esso.

class ProjectManagerChecker 
    def self.matches?(request) 
    request.env['warden'].user.role == 'project_manager' 
    end 
end 

# routes.rb 
get '/' => 'project_managers#index', :constraints => ProjectManagerChecker 
get '/' => 'clients#index' 

Se il ruolo dell'utente è "project_manager" il ProjectManagersController saranno utilizzati - se non è verrà utilizzato il ClientsController. Se non hanno effettuato il login, env['warden'].user sarà nullo e si verificherà un errore, quindi probabilmente vorrai ovviare a questo, ma questo ti consentirà di iniziare.

+0

Grazie per aver risposto! In realtà ho provato prima questo, ma non ho potuto farlo funzionare (probabilmente perché sono nuovo a questo). Per non parlare - a questo punto riesco a capire a malapena cosa sto facendo, quindi l'idea di "sperimentare con essa" è spaventosa da morire! – Mark

13

La soluzione più semplice è quella di utilizzare lambda:

root :to => 'project_managers#index', :constraints => lambda { |request| request.env['warden'].user.role == 'project_manager' } 
root :to => 'clients#index' 
+0

Ha funzionato per me. Ho una domanda però. Sto usando Ruby 2.3.0 e mi permette di usare la nuova sintassi lambda di stabby. Ma sto riscontrando un errore di sintassi con 'constraints: -> {...}'. Funziona bene se uso 'lambda' invece di' -> '. Qualche idea su questo? – artificis

10

Un'altra opzione è quella di passare un proc al metodo authenticated come questo (sto usando in questo rolify esempio):

authenticated :user, ->(u) { u.has_role?(:manager) } do 
    root to: "managers#index", as: :manager_root 
end 

authenticated :user, ->(u) { u.has_role?(:employee) } do 
    root to: "employees#index", as: :employee_root 
end 

root to: "landing_page#index" 

si noti che in Rails 4 si avete a sPECIF y un nome univoco per ciascuna rotta principale, vedere this issue per i dettagli.

+1

questa soluzione è molto pulita con la sintassi aggiornata –

Problemi correlati