2011-09-03 19 views
6

Sono nuovo per le rotaie e sto lavorando alla mia seconda app per rotaie.Struttura del modello di rotaie per gli utenti

L'applicazione avrà diversi ruoli per gli utenti, ma alcuni utenti avranno più ruoli.

Ogni utente del sito sarà un artista. Alcuni utenti avranno il ruolo di moderatore.

Come dovrei strutturare questo? In alcune app PHP che ho utilizzato, c'è solo un utente e quindi una colonna di database per is_admin, ecc. Ma ho guardato l'origine per le app per rails e ho visto modelli separati per User e Admin, ecc. non sono sicuro del perché

Quindi, dovrei avere un singolo modello utente con un attributo di ruolo, che potrebbe essere moderatore, e quindi chiamare gli utenti "Artisti" nelle mie viste, percorsi, ecc.?

O dovrei avere un modello utente, un modello di moderatore che eredita da esso e un modello di artista che appartiene all'utente?

Sono davvero confuso.

risposta

7

È possibile cercare gemme Devise e CanCan. Questa coppia è una combinazione davvero potente. Questo rende due modelli utente e ruolo. Nel ruolo è possibile creare nuovi ruoli, senza creare nuovi modelli per loro. Sebbene crei l'Abilità del modello, qui puoi definire le regole di accesso per i ruoli.

manuale: http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/

Qui si possono trovare fonti e wikies di elaborare e CanCan di:

https://github.com/plataformatec/devise

https://github.com/ryanb/cancan

I miei modelli aspetto:

ruolo.rb

class Role < ActiveRecord::Base 
    has_and_belongs_to_many :users 
end 

User.rb

class User < ActiveRecord::Base 
    has_many :accounts 
    has_and_belongs_to_many :roles 

    # Include default devise modules. Others available are: 
    # :token_authenticatable, :confirmable, :lockable and :timeoutable 
    devise :database_authenticatable, 
     :recoverable, :rememberable, :trackable, :validatable 

    # Setup accessible (or protected) attributes for your model 
    attr_accessible :email, :username, :password, :password_confirmation, :remember_me, :role_ids 

    def role?(role) 
    return !!self.roles.find_by_name(role.to_s.camelize) 
    end 

end 

Ability.rb

class Ability 
    include CanCan::Ability 

    def initialize(user) 
    user ||= User.new # guest user 

    if user.role? :administrator 
     can :manage, :all 
    elsif user.role? :operator 
     can :read, Account 
     can :read, Server 
    elsif user.role? :customer 
     can :manage, Account 
     can :read, Server 
    end 
    end 
end 

Nel controllore è necessario aggiungere solo questo due linee:

class YourController < ApplicationController 
    before_filter :authenticate_user! 
    load_and_authorize_resource 

    ... 

end 
+0

Questo sarebbe stato il mio suggerimento. Quello che mi piace di questo approccio è che incoraggia la separazione della politica aziendale dal resto della logica dell'applicazione. –

+0

Sì questa separazione offre buone e flessibili capacità. L'ho usato in un progetto, in cui gli sviluppatori hanno creato un sistema di autenticazione molto scomodo, dove per aggiungere nuovi ruoli e abilità ho dovuto scrivere molto codice in ogni controller e modello. Ho dedicato molto tempo alla rimozione del vecchio sistema e quasi due ore per l'installazione e la configurazione di Devise e CanCan. Ora sono felice. E quando avrò tempo libero, ho intenzione di scrivere un'interfaccia utente per gestire ruoli e abilità. Con questi sistemi questo compito è diventato semplicemente. –

+0

lo abbiamo usato in diverse applicazioni e troviamo anche che il mix di cancan-devise è l'approccio "best-of-breed". Viene rapidamente adottato da molte organizzazioni come standard di quest'anno per l'autenticazione/autorizzazione. –

2

Penso che non sia necessario creare modelli diversi perché non si dispone di campi specifici per ognuno. Quindi devi solo impostare il "ruolo" di ciascun utente. Due opzioni: creare una tabella di ruolo o aggiungere un campo ruolo nella tabella Utente. Entrambe le soluzioni funzionano, la seconda è più flessibile ma meno ottimizzata.

Ma, nel caso specifico, non si dispone di una gestione dei ruoli complessa in modo da poter trovare una soluzione più semplice. Se tutti i tuoi utenti sono artisti, non devi specificarli nel tuo codice, è contenuto nella descrizione implicita di cosa sia un utente. Quindi devi solo salvare se un utente è un amministratore o no e penso che la soluzione migliore sia creare un campo booleano "is_admin".

Dopo di che si dovrà creare qualche before_filter nel vostro controller protette, come quella:

before_filter => :authorize, :only => :new, :edit, :create, :update, :destroy 

def authorize 
    redirect_to :root if not current_user.is_admin? 
end 

E si può avere semplici richieste del genere:

@artists = User.all 
@moderators = User.where(:is_admin => true) 

Se cercate un altro sistema di autorizzazione completo è possibile controllare questo piccolo gioiello: https://github.com/ryanb/cancan

Ma penso che non sia il caso per il momento. Se hai un problema semplice cerca una soluzione semplice!

+1

I valori booleani in AR producono metodi 'foo?' Che sono ottimi per condizionali, e Ruby ha un 'se non' migliore nella forma di 'unless'. Combinando insieme: 'redirect_to: root unless current_user.is_admin?' – coreyward

+0

Una buona annotazione per l'helper ActiveRecord, non lo sapevo! –

+0

+1 per soluzioni semplici. La cosa bella di ruby ​​è che puoi usare il campo booleano e mantenere l'interfaccia 'is_admin?' Quando cambi in un modello di ruolo separato o qualcos'altro. –

2

Se avete bisogno di avere un codice specifico e un ruolo o un amministratore o moderatore un'altra soluzione sarebbe quella di creare un modello utente di base da cui ereditano tutte le altre classi. È quindi possibile creare una classe di amministrazione e una classe moderatore che ereditano dal modello utente. Ciò significa che puoi evitare di controllare costantemente il ruolo degli utenti nel tuo codice, ad es. current_user.do_some_admin_thing if current_user.is_admin?. Le tue lezioni sarebbero simile a questa

class User < ActiveRecord::Base 
    # base user methods in here 
end 

class Moderator < User 
    def do_moderator_thing 
    # perform a moderator task 
    end 
end 

class Admin < Moderator 
    def do_admin_thing 
    # perform an admin task 
    end 
end 

In questo caso la classe utente ha i privilegi più elementari, i moderatori possono fare gli utenti tutto può più i metodi e gli amministratori specifici moderatore può fare agli utenti tutto e moderatori CAN più l'amministratore specifici metodi.

Tutti i diversi ruoli utente utilizzerebbero la stessa tabella nel database ma le vostre preoccupazioni sono ordinatamente separate in classi che evitano condizionali eccessivi attraverso il codice che controlla il ruolo che l'utente ha sempre.

Creazione di nuovi utenti sarebbe semplice anche per Admin.new :name => 'bob' la classe di amministrazione quindi si cura di come un utente è definito come un amministratore che fornisce una bella interfaccia in cui non è necessario conoscere il funzionamento interno del sistema di ruolo per interagire con utenti.

+0

Si prega di modificare la domanda in modo esplicito sul fatto che si sta utilizzando l'ereditarietà della tabella singola e il collegamento alla documentazione ufficiale delle guide su di esso. –

+0

La domanda non parla di comportamenti diversi per utenti diversi, solo autorizzazioni diverse per fare cose diverse. A meno che l'istanza di modelli User non si comporti in modo diverso, è eccessivamente complesso creare sottoclassi diverse. L'abuso di ereditarietà è un anti-modello. – Winfield

1

Anche se io sono d'accordo la combinazione di Devise e CanCan è potente e lavora. Vediamolo con una prospettiva diversa tenendo conto dell'Associazione e della Delegazione.

Association: Nella programmazione orientata agli oggetti, associazione definisce una relazione tra classi di oggetti che permette un oggetto esempio per causare un altro per eseguire un'azione per suo conto.

Delega: Delega consente di definire il comportamento di un oggetto in in termini di comportamento di un altro oggetto. Il termine "delegazione" si riferisce alla delega di responsabilità. L'enfasi primaria della delega è sul passaggio dei messaggi in cui un oggetto può delegare a la responsabilità di un messaggio che non è in grado di gestire gli oggetti che potenzialmente potrebbero (i suoi delegati).

Con ciò, cosa succede se progettiamo il nostro utente e ruoli come questo. Non esiste una classe Role e l'Utente non eredita o non specializza una particolare classe (Artist, Admin), invece, tutte le classi (Role) contengono l'oggetto User e delegate. Il modo in cui sto pensando e modo per implementare con Rails è qualcosa di simile:

class User < AR::Base 
    def user_method 
    end 
end 

class Artist < AR::Base 
    has_one :user 

    def artist_method 
    # perform an admin task 
    end 
end 

class Admin < AR::Base 
    has_one :user 

    def admin_method 
    # perform an admin task 
    end 
end 

Questo role class model è descritto da Francis G. Mosse in suo articolo su ruoli modellazione.

1

Questa è la configurazione di base, per la gemma declarative authorization, io uso. Ma potreste semplicemente usarlo così com'è senza la gemma, se i vostri requisiti di autorizzazione non sono altro che chiedere il tipo di ruoli che l'utente ha.

Richiede una tabella roles e tale, in modo che potrebbe non essere proprio la vostra fantasia.

class Role < ActiveRecord::Base 
    belongs_to :user 
end 

class User < ActiveRecord::Base 
    has_many :roles 

    def role_symbols 
    roles.map { |r| r.title.to_sym } 
    end 

    def admin? 
    has_role?(:admin) 
    end 
    # include more role booleans or write some ruby magic to be DRY 
    # ... 

    def has_role?(r) 
    role_symbols.include?(r.to_sym) 
    end 
end 

# give or take 
user = User.new 
user.roles << Role.new :title => "admin" 
user.roles << Role.new :title => "artist" 

user.role_symbols # => [:admin, :artist] 
user.admin? # => true 
user.has_role?(:artist) # => true 
0

È possibile avere due modelli Utente e Ruolo. E il ruolo appartiene all'utente.

Specificare il ruolo degli utenti (come amministratore, moderatore) nel modello di ruolo.

Problemi correlati