Ci sono diversi modi per affrontare questo problema, come indicano altre risposte. Innanzitutto, assicurarsi di comprendere la differenza tra l'autenticazione , (creazione di un utente e accesso) e l'autorizzazione basata su ruolo (controllare l'accesso a diverse parti dell'applicazione Web in base al ruolo dell'utente). È possibile implementare l'autenticazione da soli, ma la maggior parte degli sviluppatori Rails utilizza la gemma Devise perché è robusta, completa e ben collaudata. L'autorizzazione può essere implementata con semplici aggiunte a un modello Utente, sebbene gli sviluppatori spesso usino le gemme CanCanCan o Pundit per applicazioni complesse.
Per il caso d'uso che descrivi, ti consiglio di implementare una forma molto semplice di autorizzazione basata sui ruoli nel tuo modello Utente. Per prima cosa dovrai creare un modello utente usando Devise.
Una nuova funzionalità di Active Record, Enum, introdotta in Rails 4.1, è il modo più semplice per implementare l'autorizzazione basata sui ruoli.
Creare una migrazione:
$ rails generate migration AddRoleToUsers role:integer
La migrazione sarà simile a questa:
class AddRoleToUsers < ActiveRecord::Migration
def change
add_column :users, :role, :integer
end
end
aggiungere il codice per il vostro modello User per l'attuazione del Enum:
class User < ActiveRecord::Base
enum role: [:student, :parent, :teacher, :admin]
after_initialize :set_default_role, :if => :new_record?
def set_default_role
self.role ||= :student
end
end
si definisce il i nomi dei ruoli e, se necessario, possono modificare i nomi secondo necessità (i valori interi memorizzati con ciascun utente) il cavo rimane invariato). Active Record limiterà l'assegnazione dell'attributo a una raccolta di valori predefiniti, quindi non è necessario aggiungere alcun codice per limitare i nomi dei ruoli a un set definito. Meglio di tutto, le enumerazioni vengono fornite con una serie di metodi di convenienza che consentono di interrogare direttamente il ruolo senza alcun codice aggiuntivo. Per l'attributo enum mostrato sopra, è possibile utilizzare questi metodi:
User.roles # => {"student"=>0, "parent"=>1, "teacher"=>2, "admin"=>1} # list all roles
user.student! # make a student user
user.student? # => true # query if the user is a student
user.role # => "student" # find out the user’s role
@users = User.student # obtain an array of all users who are students
user.role = 'foo' # ArgumentError: 'foo' is not a valid, we can’t set invalid roles
è possibile utilizzare il condizionali in un controllore:
class UsersController < ApplicationController
def index
unless current_user.admin?
redirect_to :back, :alert => "Access denied."
end
@users = User.all
end
end
o usarlo in una vista:
<% if current_user.parent? %>
<li><%= link_to 'Grade Reports', some_path %></li>
<% end %>
In generale, se il controllo degli accessi aggiunge molto codice a un controller, si consiglia di utilizzare CanCanCan o Pundit, perché è possibile spostare la complessa logica di autorizzazione in un centro posizione separata dai controllori ("skinny controller"). Tuttavia, se le tue esigenze sono semplici come descrivi, l'autorizzazione basata sul ruolo nel controller è ottimale.
Ho scritto un'esercitazione Rails Pundit che confronta entrambi gli approcci e fornisce maggiori dettagli sulla semplice autorizzazione basata sui ruoli e sull'autorizzazione basata su ruoli con Pundit.
'type'attribute è riservato all'ereditarietà di una singola tabella, cosa potrebbe essere appropriato in questo caso, ma almeno è necessario specificare che questa risposta implichi STI e che il modello Studente e Insegnante debba ereditare dall'utente. –
grazie per il tuo commento @ CV-Gate. Ho modificato la mia risposta. Qui non sto usando STI. – lsaffie