2013-08-28 19 views
7

Obecnie utknąłem na temat oddzielania ról dla CanCan w zależności od każdego warunku, który chcemy. W naszej aplikacji znajduje się wiele kategorii (takich jak matematyka, język angielski, historia itp.), A w ramach każdego z nich jest wiele kursów.Szyny: Używanie CanCan do definiowania wielu ról w zależności od instancji pojedynczego modelu?

Każdy użytkownik może mieć wiele różnych ról w każdej kategorii. Na przykład John może być "czytelnikiem" matematyki, co oznacza, że ​​potrafi czytać wszystkie kursy matematyki. John może również być "pisarzem" dla języka angielskiego, co oznacza, że ​​może czytać wszystkie kursy w języku angielskim, utworzyć kurs w kategorii angielski i edytować/usuwać tylko kursy, które stworzył w języku angielskim.

Gdyby to były jedyne role, jakie miał John, nie byłby w stanie zobaczyć historii kategorii w pasku nawigacyjnym i nie otrzymałby dostępu do kursów w historii.

Są jak relacje są skonfigurowane:

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 

w modelu/ability.rb mamy

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 

pytania:

  1. Jak rozdzielić role "czytnik" i "pisarz" we właściwy sposób? W jaki sposób uzyskujemy dostęp do kursów należących do kategorii, do których mamy dostęp?

  2. Po zdefiniowaniu metod czytnika i pisarza w pliku ability.rb, w jaki sposób wykorzystujemy je na naszych stronach widoków? Wygląda na to, że obecne dokumenty używają czegoś takiego jak "<%, jeśli można?: Odczytać, @ kategoria%> ", ale to nie wykorzystuje metod, które rozdzieliliśmy i zdefiniowaliśmy.

p.s. Będziemy mieli 7 różnych ról: gość, czytelnik, pisarz, redaktor, menedżer, administrator i app_admin (nasi programiści)

Próbowałem rozwiązać ten problem przez 3 dni - proszę, zrozum, że wciąż jestem sprawiedliwy Początkujący! Z góry dziękuję

Odpowiedz

-2

W swoim pliku gem zawiera.

  1. gem "kankan"

  2. zainstalować paczkę.

  3. szyny g kankana: umiejętność

ten wygeneruje klasy umiejętności w swoich modelach.

Zdefiniuj swoje Zdolności tam jak poniżej.

ale należy pamiętać, że już zdefiniowane role,

takie jak masz model użytkownika,

mający dwie role zdefiniowane tj admina i wsparcia.

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. zasób, w którym chcesz ograniczyć użytkownika, kliknąć na poniższy filtr w swoim kontrolerze.

   load_and_authorize_resource 

5. jeśli chcesz ograniczyć coś w widokach, aby nie pokazać.

<% 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

Wpadłem dziś na te same potrzeby i znalazłem sposób na zrobienie tego na CanCan Wiki.

Proste następujące czynności:

1) Tworzenie stałej mocy klasy User ze swoimi nazwami ról:

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

2a) utworzyć i uruchomić migrację jeśli używasz ActiveRecord:

rails generate migration add_roles_mask_to_users roles_mask:integer 
rake db:migrate 

2b) Dodaj te pola na modelu użytkownika, jeśli używasz Mongoid:

field :roles_mask, type: Integer 

3) Następnie trzeba dodać następujący kod do modelu użytkownika:

# 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) Jeśli używasz opracować bez mocnych parametrów, nie zapomnij dodać attr_accessible: role Ty model użytkownika. Jeśli korzystasz z strong_parameters opracowania, albo jako klejnot w Rails 3 aplikacji, lub jak jest wbudowany w Rails 4, nie zapomnij dodać role do dozwolonej listy w kontrolerze:

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) Dodaj kod poniżej, aby wygenerować wyboru z punktu widzenia ustalania tych ról:

<% 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) Wreszcie, można następnie dodać wygodny sposób sprawdzić role użytkownika w klasie Ability:

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

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

To wszystko.

Mam nadzieję, że to może pomóc.

Powiązane problemy