Utilizzando le gemme CanCan e Role, ciò che è ancora necessario è un modo per controllare il percorso e vedere se "current_user" ha le autorizzazioni per accedere a quella rotta in base al ruolo o ai ruoli, quindi mostrare/nascondere in base a ciò.
Ciò consente di risparmiare il clic dell'utente sulle cose e sempre detto che non possono vederlo - oppure dover scrivere per-voce "se" logica specificare quali ruoli possono vedere ciò che list-elementi (quali il cliente cambia periodicamente, come i ruoli vengono modificati/perfezionati) attorno a ogni singolo link nel menu di uno (considera un menu di bootstrap con oltre 50 elementi nidificati in gruppi con formattazione HTML, ecc.), che è folle.
Se dobbiamo mettere la logica if in ogni voce di menu, usiamo la stessa logica per ogni elemento controllando il ruolo/le autorizzazioni che abbiamo già definito nel file Abilità.
Ma nella nostra lista di menu, abbiamo helper di route - non informazioni "controller/metodo", quindi come testare la capacità dell'utente di colpire l'azione del controller specificata per il "percorso" in ciascun collegamento?
Per ottenere il controller e il metodo (azione) di un percorso (i miei esempi si utilizza il 'users_path' itinerario-helper) ...
Rails.application.routes.recognize_path(app.users_path)
=> {:controller=>"users", :action=>"index"}
ottenere solo il nome del controller
Rails.application.routes.recognize_path(app.users_path)[:controller]
=> "users"
abilità usa il modello per la sua ripartizione, in modo da convertire da nome del controllore ad esso è il modello (assumendo la denominazione di default usata) ...
Rails.application.routes.recognize_path(app.users_path)[:controller].classify
=> "User"
ottenere solo l'azione nome
Rails.application.routes.recognize_path(app.users_path)[:action]
=> "index"
E poiché il "può?" metodo ha bisogno di un simbolo per l'azione, e Constant per il modello, per ogni voce di menu otteniamo questo:
path_hash = Rails.application.routes.recognize_path(app.users_path)
model = path_hash[:controller].classify.constantize
action = path_hash[:action].to_sym
Poi utilizzare il nostro sistema abilty esistente per verificare se il current_user può accedervi, dobbiamo passare il azione come un simbolo e il modello come una costante, in modo da ...
<% if can? action model %>
<%= link_to "Users List", users_path %>
<% end %>
Ora siamo in grado di cambiare chi può vedere questa risorsa e il link dal file Ability, senza mai fare scherzi con il menu, ancora una volta. Ma per rendere questo un po 'più pulita, ho estratto la ricerca per ogni voce di menu con questo in app-Controller:
def get_path_parts(path)
path_hash = Rails.application.routes.recognize_path(path)
model_name = path_hash[:controller].classify.constantize
action_name = path_hash[:action].to_sym
return [model_name, action_name]
end
helper_method :get_path_parts
... così ho potuto fare questo nella vista (ho tirato fuori tutto il html-formattazione da collegamenti per la semplicità, qui):
<% path_parts = get_path_parts(users_path); if can?(path_parts[1], path_parts[0]) %>
<%= link_to "Users Listing", users_path %>
<% end %>
... e per fare questo ci vuole tutto il giorno digitando questi per-voci di menu IF-impacchi, ho usato regex trova/sostituisci con la cattura e caratteri jolly per avvolgere questo elenco attorno ad ogni elemento della lista di menu in un unico passaggio.
Non è l'ideale, e potrei fare molto di più per renderlo molto migliore, ma non ho tempo libero per scrivere il resto di questo pezzo mancante del sistema Role/CanCan. Spero che questa parte aiuti qualcuno.
+1 per [pundit] (https://github.com/elabs/pundit); confronto con "mainstream" [CanCan] (https: // github.com/ryanb/cancan) più facile da capire come esplicita, stessa facilità d'uso nelle viste e logica dei controller, e molto più flessibile (non complicato quando usato insieme a [rolify] (https://github.com/EppO/rolify)) Fortemente consigliato anche qui! – CloudRide
Scegli questo come risposta corretta. Non mi è piaciuta molto la mia risposta. : P –