2014-06-29 12 views
14

Tôi mới dùng Ruby on Rails và đã làm theo hướng dẫn. Nhưng tôi cần thêm thông tin.Nhiều loại người dùng trên Ruby on Rails

Tôi đang tạo ứng dụng cho phép truy cập vào nhiều loại người dùng khác nhau, họ, sinh viên, phụ huynh, giáo viên và Quản trị viên (tất cả đều có cùng thuộc tính) Cho đến nay tôi có mô hình cho Người dùng, có các trường , Email và Mật khẩu, làm thông tin đăng nhập để đăng nhập vào trang web ..

Sau đó, tôi có mẫu cho từng loại người dùng. Sinh viên mẫu Giáo viên mẫu ....

Điều tôi muốn biết là làm cách nào để đăng ký người dùng, tham chiếu từng loại người dùng và tôi đã có Người dùng bảng.

Tôi đã tìm kiếm và tôi nhận ra rằng việc sử dụng 'phát minh' sẽ là giải pháp khả thi, nhưng không hoàn toàn hiểu cách hoạt động của nó.

Có người giải thích cho tôi cách tốt nhất để làm điều này?

Trả lời

0

Ở dạng đơn giản nhất, bạn muốn có thể chọn loại người dùng khi đăng ký.

class User 
    belongs_to: user_type 
end 

class UserType 
    has_many: users 
end 

Dựa trên mối quan hệ đơn giản một-nhiều, bạn có thể vượt qua trong các user_type theo hình thức với bộ điều khiển và để cho các bộ điều khiển chăm sóc tạo/gắn đối tượng

user = User.create(params[:user]) 
user.user_type = UserType.find(params[:user][:user_type]) 

Đó là một số rất đơn giản và nhanh chóng đặt cùng mã với ý định làm cho quan điểm của tôi rõ ràng hơn một chút.

+0

'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. –

+0

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

2

Vâng, đây là cách tôi sẽ triển khai.

1) tạo mô hình tài khoản và thêm một tài liệu tham khảo đa hình trong việc di chuyển của nó như thế này

class Account < ActiveRecord:Migration 
    def change 
     create_table :accounts do |t| 
     t.references :user, :polymorphic => true 
     t.column :name, :string 
     end 
    end 
    end 

2) Ở mỗi lớp mô hình, đối với lớp sinh viên dụ tôi sẽ thêm dòng mã sau đây

class Student < ActiveRecord::Base 
    has_one :account, :as => :user 
    end 

3) Trong mô hình class Account

class Account < ActiveRecord::Base 
    belongs_to :user, :polymorphic => true 
    end 

4) Sử dụng máy phát điện devise cho A mô hình ccount.

5) Thách thức lớn là tạo một Sinh viên mới, về cơ bản bạn sẽ tạo một bản ghi Tài khoản, sau đó gán bản ghi Tài khoản này cho hồ sơ Học viên mới được tạo.

a) Có 2 cách để làm như vậy: * Sử dụng biểu mẫu lồng nhau. * Sử dụng một biểu mẫu đơn giản và làm cho bộ điều khiển thực hiện công việc.

Tôi sẽ khuyến khích lựa chọn thứ hai, chọn những gì phù hợp nhất với bạn và cho tôi biết nếu bạn có bất kỳ vấn đề gì.

+0

Cảm ơn câu trả lời. Có lẽ tôi không rõ lắm, nhưng tôi đã có một trang để tạo người dùng, thông qua Mô hình Người dùng của tôi (tôi có thể đăng nhập và đăng xuất và xác thực tất cả dữ liệu cho 'bảng' này).Bây giờ, tôi muốn có dữ liệu của cả hai mô hình (User và UserType - Student/Parents/Admin/etc) trong cùng một trang và sau đó lưu tất cả dữ liệu vào các mô hình tương ứng của họ. – telma

1

Nếu các quyền ứng dụng khác nhau là những gì bạn cần, có lẽ bạn muốn chỉ định vai trò cho người dùng của mình. Điều này có thể được thực hiện theo nhiều cách khác nhau.Một cách dễ dàng là sử dụng đá quý Rolify: https://github.com/EppO/rolify

28

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.

+1

Câu trả lời rất hay! Một nhận xét nhỏ: Tôi nhận được một lỗi nói rằng tôi không thể có một trường ": parent" bên trong enum, bởi vì lớp này đã có một phương thức "cha mẹ", được định nghĩa bởi Active Record. –

+0

điều này thật tuyệt vời, cảm ơn bạn. –