2013-08-28 20 views
7

Attualmente sono bloccato su come separare i ruoli per CanCan in base a ciascuna condizione che desideriamo. Nella nostra applicazione, ci sono molte categorie (come matematica, inglese, storia, ecc.) E all'interno di ognuno ci sono molti corsi.Rails: utilizzare CanCan per definire più ruoli in base alle istanze del singolo modello?

Ogni utente può avere molti ruoli diversi in ciascuna categoria. Ad esempio, John può essere un "lettore" per la matematica, il che significa che può leggere tutti i corsi che sono in matematica. John può anche essere uno "scrittore" per l'inglese, il che significa che può leggere tutti i corsi in inglese, creare un corso nella categoria inglese e modificare/eliminare solo i corsi che ha creato in inglese.

Se questi fossero gli unici ruoli che John aveva, non sarebbe in grado di vedere la cronologia delle categorie nella barra di navigazione e gli sarebbe negato l'accesso ai corsi che si trovano nella cronologia.

Questi sono come le relazioni sono istituiti:

class User < ActiveRecord::Base 
    has_many :roles 

    def has_role?(role_sym) 
    roles.any? { |r| r.level.underscore.to_sym == role_sym } 
    end 
end 

class Category < ActiveRecord::Base 
    has_many :roles 
    has_many :courses 
end 

class Role < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :category 
    attr_accessible :level, :category_id, :user_id 
end 

nel modello/ability.rb abbiamo

class Ability 
include CanCan::Ability 

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

    if user.has_role? :reader 
    reader(user) 
    end 

    if user.has_role? :writer 
    writer(user) 
    end 
end 

#BE ABLE TO SEE COURSES AND CATS FOR PERMITTED CATS. 
def reader(user) 
    can :read, Category, :roles => { :user_id => user.id, :level => "reader" } 
    ## how would we be able to limit reading of courses that are within permitted categories? something like category.courses ~~ 
end 

def writer(user) 
    reader(user) #inheriting from reader? this doesnt work because level is hardcoded into reader 
    can :read, Category, :roles => { :user_id => user.id, :level => "writer"} 
    # 1.you can read all courses in category that you are given permission to 
    # 2.you can write courses in permitted category 
    # 3.you can edit, delete courses that only youve created within permitted category 
end 
end 

Domande:

  1. Come si fa a separare i ruoli di "lettore" e "scrittore" nel modo corretto? Come possiamo accedere ai corsi che rientrano nelle categorie a cui abbiamo accesso?

  2. Dopo aver definito i metodi di lettura e scrittura nell'abilità.rb, come li usiamo nelle pagine di visualizzazione? Sembra che le attuali documentazioni usino qualcosa come "<% se possibile?: Read, @category%> " ma questo non usa i metodi che abbiamo separato e definito.

p.s. Avremo 7 diversi ruoli: guest, reader, writer, editor, manager, admin e app_admin (i nostri sviluppatori)

Ho cercato di risolvere questo per 3 giorni ora - per favore, capisco che sono ancora abbastanza un principiante! Grazie in anticipo

risposta

-2

Nel tuo gemfile Include.

  1. gioiello "Cancan"

  2. installare bundle.

  3. rotaie g Cancan: capacità

questo genererà una classe di capacità nei tuoi modelli.

definire le tue abilità lì come di seguito.

ma tenete ricordate che avete già definito ruoli,

quali si dispone di un modello User,

avere due ruoli definiti di amministrazione cioè e sostegno.

class Ability 
     include CanCan::Ability 
     def initialize(user) 
     user||= User.new 
      can :read, :all 
     if user.role == 'admin' 
      can :manage, :all 
     else 
      can :read, :all 
      end 
     end 
    end 

4. la risorsa su cui si desidera limitare un utente, utilizzare il seguente filtro nella loro controllore.

   load_and_authorize_resource 

5. se si vuole limitare l'qualcosa nelle viste di non mostrare.

<% if can? :manage, @flower %> 
    <td><%= link_to 'Edit', edit_flower_path(flower) %></td> 
    <% end %> 
    <% if can? :manage, @flower %> 
     <td><%= link_to 'Destroy', flower_path(flower), method: :delete, data: { confirm: 'Are you sure?' } %></td> 
    <% end %> 
0

mi sono imbattuto in un stesse esigenze di oggi e hanno trovato un modo per fare questo su CanCan Wiki.

semplici seguire questi semplici passi:

1) Creare una costante sotto la classe User con i tuoi nomi dei ruoli:

class User < ActiveRecord::Base 
    ROLES = %w[admin moderator author banned] 
end 

2a) creare ed eseguire una migrazione se si utilizza ActiveRecord:

rails generate migration add_roles_mask_to_users roles_mask:integer 
rake db:migrate 

2b) Aggiungi questi campi sul modello User se si utilizza Mongoid:

field :roles_mask, type: Integer 

3) Dopodiché è necessario aggiungere il seguente codice al modello User:

# in models/user.rb 
def roles=(roles) 
    self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.inject(0, :+) 
end 

def roles 
    ROLES.reject do |r| 
    ((roles_mask.to_i || 0) & 2**ROLES.index(r)).zero? 
    end 
end 

4) Se si sta utilizzando concepire senza parametri forti, non dimenticate di aggiungere attr_accessible: ruoli tu modello utente. Se stai usando elaborare con strong_parameters, sia come un gioiello in un Rails 3 app, o come è incorporato in Rails 4, non dimenticate di aggiungere i ruoli alla lista consentita nel controller:

class ApplicationController < ActionController::Base 
    before_filter :configure_permitted_parameters, if: :devise_controller? 

    protected 

    def configure_permitted_parameters 
    devise_parameter_sanitizer.for(:sign_up) {|u| u.permit(:email, :password, :password_confirmation, roles: [])} 
    end 
end 

5) Aggiungere il codice qui sotto per generare caselle di controllo nella visualizzazione per impostare questi ruoli:

<% for role in User::ROLES %> 
    <%= check_box_tag "user[roles][#{role}]", role, @user.roles.include?(role), {:name => "user[roles][]"}%> 
    <%= label_tag "user_roles_#{role}", role.humanize %><br /> 
<% end %> 
<%= hidden_field_tag "user[roles][]", "" %> 

6) Infine, è possibile aggiungere un modo comodo per controllare i ruoli degli utenti nella classe Abilità:

# in models/user.rb 
def is?(role) 
    roles.include?(role.to_s) 
end 

# in models/ability.rb 
can :manage, :all if user.is? :admin 

Questo è tutto.

Spero che questo possa essere d'aiuto.