2013-08-28 97 views
7

Tôi hiện đang bị mắc kẹt về cách tách vai trò cho CanCan tùy thuộc vào từng điều kiện mà chúng tôi muốn. Trong ứng dụng của chúng tôi, có nhiều loại (chẳng hạn như toán học, tiếng anh, lịch sử, vv) và trong mỗi loại có nhiều khóa học.Đường ray: Sử dụng CanCan để xác định nhiều vai trò tùy thuộc vào trường hợp của một Mô hình đơn lẻ?

Mỗi người dùng có thể có nhiều vai trò khác nhau trên mỗi danh mục. Ví dụ, John có thể là một "người đọc" cho toán học, có nghĩa là anh ta có thể đọc tất cả các khóa học trong toán học. John cũng có thể là một "nhà văn" cho tiếng Anh, có nghĩa là anh ta có thể đọc tất cả các khóa học bằng tiếng Anh, tạo ra một khóa học trong thể loại tiếng Anh, và chỉnh sửa/xóa chỉ các khóa học anh ta tạo ra trong tiếng Anh.

Nếu đây là những vai trò duy nhất mà John có, anh sẽ không thể xem lịch sử danh mục trong thanh điều hướng và sẽ bị từ chối truy cập vào các khóa học trong lịch sử.

Đây là cách quan hệ được thiết lập:

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 

trong mô hình/ability.rb chúng tôi có

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 

Câu hỏi:

  1. Làm thế nào để chúng ta tách vai trò của "người đọc" và "nhà văn" theo cách chính xác? Làm cách nào để chúng tôi truy cập các khóa học nằm trong các danh mục mà chúng tôi có quyền truy cập?

  2. Sau khi xác định phương thức người đọc và người viết trong khả năng.rb, làm cách nào chúng tôi sử dụng chúng trong các trang xem của chúng tôi? Có vẻ như các tài liệu hiện tại sử dụng một cái gì đó như "<% nếu có thể?: Đọc, @category%> " nhưng điều đó không sử dụng các phương pháp mà chúng tôi đã tách và xác định.

p.s. Chúng tôi sẽ có 7 vai trò khác nhau: khách mời, người đọc, nhà văn, biên tập viên, người quản lý, quản trị và app_admin (nhà phát triển của chúng tôi)

Tôi đã cố gắng giải quyết điều này trong 3 ngày - hãy hiểu rằng tôi vẫn khá một người mới bắt đầu! Cảm ơn trước

Trả lời

-2

Trong gemfile của bạn Bao gồm.

  1. gem "Cancan"

  2. cài đặt bó.

  3. ray g Cancan: Khả năng

này sẽ tạo ra một lớp khả năng trong mô hình của bạn.

xác định Khả năng của bạn ở đây như sau.

nhưng giữ nhớ rằng bạn đã xác định vai trò,

như bạn có một mô hình dùng,

có hai vai trò định nghĩa quản trị tức là và hỗ trợ.

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. tài nguyên mà bạn muốn giới hạn người dùng, sử dụng bộ lọc sau trong bộ điều khiển của họ.

   load_and_authorize_resource 

5. nếu bạn muốn hạn chế nội dung nào đó trong chế độ xem không hiển thị.

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

Tôi đã điều hành một nhu cầu tương tự hôm nay và tìm cách thực hiện điều này trên CanCan Wiki.

đơn giản làm theo các bước đơn giản:

1) Tạo một hằng số thuộc lớp người dùng với tên vai trò của bạn:

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

2a) Tạo và chạy một di chuyển nếu bạn đang sử dụng ActiveRecord:

rails generate migration add_roles_mask_to_users roles_mask:integer 
rake db:migrate 

2b) Thêm trường này vào Mô hình người dùng nếu bạn đang sử dụng Mongoid:

field :roles_mask, type: Integer 

3) Tiếp theo bạn sẽ cần phải thêm mã sau vào mô hình tài:

# 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) Nếu bạn đang sử dụng đưa ra không có tham số mạnh mẽ, đừng quên để thêm attr_accessible: vai trò để mô hình người dùng của bạn. Nếu bạn đang sử dụng đưa ra với strong_parameters, hoặc như là một viên ngọc trong một ứng dụng Rails 3, hoặc như là tích hợp sẵn trong Rails 4, không quên thêm những role vào danh sách cho phép trong bộ điều khiển:

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) Thêm mã dưới đây để tạo hộp kiểm trong giao diện để thiết lập các vai trò:

<% 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) Cuối cùng, bạn có thể sau đó thêm một cách thuận tiện để kiểm tra vai trò của người sử dụng trong lớp Khả năng:

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

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

Vậy đó.

Tôi hy vọng điều này có thể hữu ích.