Có một số cách để tiếp cận vấn đề này, như các câu trả lời khác cho biết. Trước tiên, hãy đảm bảo bạn hiểu sự khác biệt giữa xác thực , (tạo người dùng và đăng nhập) và ủy quyền dựa trên vai trò (kiểm soát quyền truy cập vào các phần khác nhau của ứng dụng web tùy thuộc vào vai trò của người dùng). Bạn có thể tự thực hiện xác thực nhưng hầu hết các nhà phát triển Rails đều sử dụng đá quý Devise vì nó mạnh mẽ, đầy đủ tính năng và được thử nghiệm tốt. Việc ủy quyền có thể được thực hiện với các bổ sung đơn giản cho mô hình Người dùng, mặc dù các nhà phát triển thường sử dụng các đá quý CanCanCan hoặc Pundit cho các ứng dụng phức tạp.
Đối với trường hợp sử dụng mà bạn mô tả, tôi khuyên bạn nên triển khai hình thức ủy quyền dựa trên vai trò rất cơ bản trong Mô hình người dùng của mình. Trước tiên, bạn sẽ phải tạo một mô hình người dùng bằng Devise.
Tính năng mới của Active Record, Enum, được giới thiệu trong Rails 4.1, là cách đơn giản nhất để triển khai ủy quyền dựa trên vai trò.
Tạo một di cư:
$ rails generate migration AddRoleToUsers role:integer
Việc chuyển sẽ trông như thế này:
class AddRoleToUsers < ActiveRecord::Migration
def change
add_column :users, :role, :integer
end
end
Thêm mã để mô hình tài khoản của bạn để thực hiện các 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
Bạn xác định tên của các vai trò, và nếu cần thiết, có thể thay đổi tên khi cần thiết (các giá trị số nguyên được lưu trữ với mỗi người dùng lại dây vẫn không thay đổi). Bản ghi đang hoạt động sẽ hạn chế việc gán thuộc tính cho tập hợp các giá trị được xác định trước, do đó bạn không phải thêm bất kỳ mã nào để hạn chế tên của vai trò thành tập hợp đã xác định. Hay nhất của tất cả, enums đi kèm với một tập hợp các phương pháp thuận tiện cho phép bạn trực tiếp truy vấn vai trò mà không cần thêm bất kỳ mã nào. Đối với thuộc tính enum trình bày ở trên, bạn có thể sử dụng các phương pháp:
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
Bạn có thể sử dụng các điều kiện trong một bộ điều khiển:
class UsersController < ApplicationController
def index
unless current_user.admin?
redirect_to :back, :alert => "Access denied."
end
@users = User.all
end
end
Hoặc sử dụng nó trong một cái nhìn:
<% if current_user.parent? %>
<li><%= link_to 'Grade Reports', some_path %></li>
<% end %>
Nói chung, nếu kiểm soát truy cập thêm nhiều mã vào bộ điều khiển, bạn nên sử dụng CanCanCan hoặc Pundit, vì bạn có thể di chuyển logic ủy quyền phức tạp thành một centr al vị trí tách biệt khỏi bộ điều khiển ("bộ điều khiển gầy"). Tuy nhiên, nếu nhu cầu của bạn đơn giản như bạn mô tả, ủy quyền dựa trên vai trò trong bộ điều khiển là tối ưu.
Tôi đã viết hướng dẫn Rails Pundit so sánh cả hai cách tiếp cận và cung cấp chi tiết hơn về ủy quyền dựa trên vai trò đơn giản cũng như ủy quyền dựa trên vai trò với Pundit.
'type'attribute được dành riêng cho kế thừa bảng đơn, điều có thể phù hợp trong trường hợp này, nhưng ít nhất bạn nên xác định câu trả lời này ngụ ý STI và mô hình Sinh viên và giáo viên nên kế thừa từ Người dùng. –
cảm ơn nhận xét của bạn @ CV-Gate. Tôi đã sửa đổi câu trả lời của mình. Ở đây tôi không sử dụng STI. – lsaffie