2014-06-29 21 views
14

我是Ruby on Rails的新手,並且一直在關注本教程。 但我需要更多信息。Ruby on Rails上的多種用戶類型

我正在構建一個應用程序,允許訪問各種類型的用戶,他們是學生,家長,教師和管理員(全部具有相同的屬性) 到目前爲止,我有一個用戶模型, ,電子郵件和密碼,作爲登錄到該網站的憑據..

然後我有一個模板爲每種類型的用戶。 模範學生 模範教師 ....

我想知道什麼是我該如何註冊一個用戶,指的是每種類型的用戶,而我已經有一個表用戶。

我一直在尋找,我意識到使用'設計'將是一個可行的解決方案,但不太明白這是如何工作的。

有人向我解釋這樣做的最好方法嗎?

回答

0

以其最簡單的形式,您希望能夠在註冊時選擇用戶類型。

class User 
    belongs_to: user_type 
end 

class UserType 
    has_many: users 
end 

此基礎上簡單的一個一對多的關係,你可以通過在形式向控制器USER_TYPE,讓控制器負責創建/關聯對象

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

這是一些照顧非常簡單,並迅速將代碼與意圖使我的觀點更清晰一點。

+0

'type'屬性是爲單表繼承保留的,在這種情況下可能適用,但至少應指定此答案意味着STI,學生和教師模型應從用戶繼承。 –

+0

感謝您的評論@ CV-Gate。我修改了我的答案。這裏我沒有使用STI。 – lsaffie

2

那麼,這裏是我將如何實現它。

1)創建帳戶模型,並在其遷移添加這樣

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

2多態參考)在每一模型類,例如學生類我要補充的下面一行代碼

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

3)在帳戶模型類

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

4)使用色器件發生器,用於甲ccount模型。

5)最大的挑戰是創建一個新學生,基本上你會創建一個帳戶記錄,然後將這個帳戶記錄分配給新創建的學生記錄。

a)有兩種方法可以這樣做: *使用嵌套窗體。 *使用一個簡單的表單,並讓控制器完成工作。

我會鼓勵第二種選擇,選擇最適合你的東西,並讓我知道你是否有任何問題。

+0

感謝您的回答。 也許我不是很清楚,但我已經有一個頁面來創建一個用戶,通過我的用戶模型(我可以做登錄和註銷,並驗證此'表'的所有數據)。現在,我想要在同一頁面中同時存儲模型(用戶和用戶類型 - 學生/家長/管理員/等)的數據,然後將所有數據保存到它們各自的模型中。 – telma

1

如果您需要不同的應用程序權限,那麼您可能需要爲用戶分配角色。這可以通過許多不同的方式來完成。一個簡單的方法就是使用Rolify寶石:https://github.com/EppO/rolify

28

其他答案表明有幾種方法可以解決這個問題。首先,確保您瞭解身份驗證(創建用戶並登錄)和基於角色授權(根據用戶角色控制對Web應用程序不同部分的訪問)之間的區別。您可以自己實現身份驗證,但大多數Rails開發人員使用Devise gem,因爲它的功能強大,功能全面且經過良好測試。儘管開發人員經常使用CanCanCanPundit寶石作爲複雜應用程序,但可以通過對用戶模型的簡單添加來實現授權。

對於您描述的用例,我建議在用戶模型中實施基本的基於角色的授權形式。首先,您必須使用Devise創建用戶模型。

Rails 4.1中引入的Active Record,Enum的新功能是實現基於角色的授權的最簡單方法。

創建遷移:

$ rails generate migration AddRoleToUsers role:integer 

遷移將是這樣的:

class AddRoleToUsers < ActiveRecord::Migration 
    def change 
    add_column :users, :role, :integer 
    end 
end 

代碼添加到您的用戶模型來實現的枚舉:

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 

你定義角色名稱,如有必要,可以根據需要更改名稱(與每個用戶存儲在一起的整數值)繩索保持不變)。 Active Record將限制屬性的賦值給一個預定義的值的集合,所以你不必添加任何代碼來將角色的名字限制在一個已定義的集合中。最重要的是,枚舉帶有一套便利方法,可以讓您直接查詢角色而無需額外的代碼。對於上面顯示的枚舉屬性,可以使用以下方法:

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 

可以使用條件語句中的控制單元,

class UsersController < ApplicationController 
    def index 
    unless current_user.admin? 
     redirect_to :back, :alert => "Access denied." 
    end 
    @users = User.all 
    end 
end 

或者在視圖中使用它:

<% if current_user.parent? %> 
    <li><%= link_to 'Grade Reports', some_path %></li> 
<% end %> 

一般情況下,如果訪問控制將大量代碼添加到控制器中,則建議您使用CanCanCanPundit,因爲您可以將複雜的授權邏輯移動到中心從控制器(「瘦身控制器」)分離的位置。但是,如果您的需求如您所描述的那樣簡單,那麼控制器中基於角色的授權是最佳選擇。

我寫了一本Rails Pundit教程,該教程比較了兩種方法,並提供了有關基於角色的簡單授權以及使用Pundit進行基於角色的授權的更多詳細信息。

+1

很好的答案!有點評論:我得到一個錯誤,說我不能在枚舉裏面有一個字段「:parent」,因爲這個類已經有一個方法「parent」,它由Active Record定義。 –

+0

這很好,謝謝。 –