2014-06-29 11 views
14

Sono nuovo a Ruby on Rails e ho seguito il tutorial. Ma ho bisogno di più informazioni.Più tipi di utenti su Ruby on Rails

Sto costruendo un'applicazione che consentirà l'accesso a varie tipologie di utenti, sono, studenti, genitori, insegnanti e Amministrazione (tutti hanno gli stessi attributi) Finora ho un modello per l'utente, che ha campi , Email e Password, che servono come credenziali per accedere al sito ..

Quindi ho un modello per ogni tipo di utente. studente modello Modello Maestro ....

Quello che volevo sapere era come faccio a registrare un utente, con riferimento ad ogni tipo di utente, e ho già una tabella utente.

Ho cercato e ho realizzato che l'utilizzo di "Idea" sarebbe una soluzione valida, ma non capisco come funziona.

Qualcuno mi spiega il modo migliore per farlo?

risposta

0

Nella sua forma più semplice, si desidera essere in grado di selezionare il tipo di utente al momento della registrazione.

class User 
    belongs_to: user_type 
end 

class UserType 
    has_many: users 
end 

Sulla base di quella semplice relazione uno-a-molti, è possibile passare in user_type nella forma al controller e lasciare che il controllore prendersi cura di creazione/associare oggetti

user = User.create(params[:user]) 
user.user_type = UserType.find(params[:user][:user_type]) 

che è un po ' molto semplice e rapidamente messo insieme il codice con l'intenzione di rendere il mio punto un po 'più chiaro.

+0

'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. –

+0

grazie per il tuo commento @ CV-Gate. Ho modificato la mia risposta. Qui non sto usando STI. – lsaffie

2

Bene, ecco come implementarlo.

1) creare il modello account e aggiungere un riferimento polimorfico nella sua migrazione come questo

class Account < ActiveRecord:Migration 
    def change 
     create_table :accounts do |t| 
     t.references :user, :polymorphic => true 
     t.column :name, :string 
     end 
    end 
    end 

2) In ogni classe del modello, per la classe degli studenti esempio vorrei aggiungere la seguente riga di codice

class Student < ActiveRecord::Base 
    has_one :account, :as => :user 
    end 

3) Nel modello di account classe

class Account < ActiveRecord::Base 
    belongs_to :user, :polymorphic => true 
    end 

4) Utilizzare generatore di escogitare per a modello account.

5) La grande sfida è la creazione di un nuovo Studente, in pratica creerai un record Account e assegnerai questo record Account al record Studente appena creato.

a) Ci sono 2 modi per farlo: * Uso di moduli annidati. * Usare un semplice modulo e fare in modo che il controllore lavori.

Vorrei incoraggiare la seconda opzione, scegliere ciò che si adatta meglio e fammi sapere se hai qualche problema.

+0

Grazie per la risposta. Forse non ero molto chiaro, ma ho già una pagina per creare un utente, attraverso il mio modello utente (posso fare login e logout e convalidare tutti i dati per questa 'tabella').Ora, voglio avere i dati di entrambi i modelli (User e UserType - Student/Parents/Admin/etc) nella stessa pagina e quindi salvare tutti i dati nei rispettivi modelli. – telma

1

Se le autorizzazioni di app diverse sono ciò che è necessario, forse si desidera assegnare ruoli ai propri utenti. Questo può essere realizzato in molti modi diversi.Facile da usare gemma Rolify: https://github.com/EppO/rolify

28

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.

+1

Ottima risposta! Una piccola osservazione: ho ricevuto un errore nel dire che non posso avere un campo ": parent" all'interno dell'enumerazione, perché questa classe ha già un metodo "parent", che è definito da Active Record. –

+0

questo è eccellente, grazie. –