2011-09-03 89 views
6

我是新來的rails,我正在開發我的第二個rails應用程序。用戶的導軌模型結構

該應用將爲用戶提供不同的角色,但某些用戶將擁有多個角色。

該網站的每個用戶都將是一位藝術家。一些用戶將扮演主持人的角色。

我該如何構造它?在我使用的一些PHP應用程序中,只有一個用戶,然後是is_admin的數據庫列等。但是我已經查看了rails應用程序的源代碼,並且已經看到用戶和管理員等單獨的模型,儘管我不知道爲什麼。因此,我是否應該擁有一個帶有角色屬性(可能是版主)的單個用戶模型,然後在我的視圖,路線等中調用用戶「藝術家」?

或者我應該有一個用戶模型,從它繼承的一個主持人模型,以及一個belongs_to用戶的藝術家模型?

我真的很困惑。

回答

7

你可以尋找寶石Devise和CanCan。這雙組合真的很強大。這使得兩個模型用戶和角色。在角色中,您可以創建新角色,而無需爲其創建新模型。雖然它創建了模型能力,但您可以在此定義角色的訪問規則。

手冊: http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/

在這裏你可以找到設計的和慘慘的來源和wikies:

https://github.com/plataformatec/devise

https://github.com/ryanb/cancan

我的模式是這樣的:

作用。RB

class Role < ActiveRecord::Base 
    has_and_belongs_to_many :users 
end 

User.rb

class User < ActiveRecord::Base 
    has_many :accounts 
    has_and_belongs_to_many :roles 

    # Include default devise modules. Others available are: 
    # :token_authenticatable, :confirmable, :lockable and :timeoutable 
    devise :database_authenticatable, 
     :recoverable, :rememberable, :trackable, :validatable 

    # Setup accessible (or protected) attributes for your model 
    attr_accessible :email, :username, :password, :password_confirmation, :remember_me, :role_ids 

    def role?(role) 
    return !!self.roles.find_by_name(role.to_s.camelize) 
    end 

end 

Ability.rb

class Ability 
    include CanCan::Ability 

    def initialize(user) 
    user ||= User.new # guest user 

    if user.role? :administrator 
     can :manage, :all 
    elsif user.role? :operator 
     can :read, Account 
     can :read, Server 
    elsif user.role? :customer 
     can :manage, Account 
     can :read, Server 
    end 
    end 
end 

在控制器中必須添加僅此兩行:

class YourController < ApplicationController 
    before_filter :authenticate_user! 
    load_and_authorize_resource 

    ... 

end 
+0

這應該是我的建議。我喜歡這種方法,它鼓勵將業務策略與其他應用程序邏輯分開。 –

+0

是的,這種分離給予了良好和靈活的能力。我在一個項目中使用它,在這個項目中,開發人員製作了非常不舒服的認證系統,爲了添加新角色和新功能,我必須在每個控制器和模型中編寫大量代碼。爲了安裝和配置Devise和CanCan,我花了很多時間去除舊系統,並花了將近兩個小時的時間。現在我很高興。當我有空的時候,我打算編寫用於管理角色和能力的用戶界面。有了這些系統,這個任務變得簡單。 –

+0

我們已經在幾個應用中使用了這個功能,並且我們還發現這個設計-cancan混合是'最好的'方法。許多組織很快就採用這種標準作爲今年的認證/授權標準。 –

2

我想你不必創建不同的模型,因爲你沒有爲每一個特定的字段。所以你只需要設置每個用戶的「角色」。兩個選項:在表User中創建一個角色表或添加一個角色字段。這兩種解決方案都有效,第二種解決方案更加靈活,但不夠優化

但是,在您的特殊情況下,您沒有複雜的角色管理,因此您可以找到更簡單的解決方案。如果您的所有用戶都是藝術家,您不必在代碼中指定它,它就包含在用戶隱含的描述中。所以你只需要保存,如果用戶是管理員或不,我認爲最好的解決方案是創建一個布爾字段「is_admin」。

之後,你會在你的保護控制器創建一些的before_filter,這樣的:

before_filter => :authorize, :only => :new, :edit, :create, :update, :destroy 

def authorize 
    redirect_to :root if not current_user.is_admin? 
end 

而且你可以有簡單的請求這樣的:

@artists = User.all 
@moderators = User.where(:is_admin => true) 

如果你找一個更完整的授權系統,你可以檢查這個小寶石:https://github.com/ryanb/cancan

但我認爲這不是現在的情況。如果你有一個簡單的問題尋找一個簡單的解決方案!

+1

布爾值會產生'富?'方法是偉大的條件語句和Ruby在'unless'形式更好'如果not'。這些結合在一起:'redirect_to的:除非根'current_user.is_admin好 – coreyward

+0

此話的ActiveRecord的幫手,我不知道它! –

+0

+1簡單的解決方案。關於ruby的好處在於,當您更改爲單獨的角色模型或其他類型時,您可以使用布爾字段並保留'is_admin?'接口。 –

2

如果您需要擁有特定的代碼和角色或諸如管理員或主持人一個其它的解決方案是創建一個基用戶模型,所有的其他類繼承。然後,您可以創建一個Admin類和一個從User模型繼承的Moderator類。這意味着您可以避免不斷地檢查代碼中的用戶角色,例如current_user.do_some_admin_thing if current_user.is_admin?。你的班會是這個樣子

class User < ActiveRecord::Base 
    # base user methods in here 
end 

class Moderator < User 
    def do_moderator_thing 
    # perform a moderator task 
    end 
end 

class Admin < Moderator 
    def do_admin_thing 
    # perform an admin task 
    end 
end 

在這種情況下,用戶類有最基本的權限,管理員可以做的一切用戶可以加上主持人的具體方法和管理員可以做的一切用戶和管理員可以加管理員具體方法。

所有不同的用戶角色將使用同一個數據庫中的表,但您的問題都整齊地分入你的代碼避免過多的條件語句檢查用戶是什麼樣的角色所有的時間類。

創建新用戶也很簡單Admin.new :name => 'bob' Admin類然後負責如何將用戶定義爲管理員,該管理員提供了一個很好的界面,您無需瞭解角色系統的內部工作方式用戶。

+0

請編輯你的問題,明確表明這是使用Single Table Inheritance並鏈接到它的官方rails文檔。 –

+0

這個問題並沒有提到不同用戶的不同行爲,只是不同的授權來做不同的事情。除非用戶模型的實例實際上行爲不同,否則創建不同的子類過於複雜。過度使用繼承是一種反模式。 – Winfield

1

雖然我同意設計的結合,康康舞是強大的和作品。讓我們以不同的角度來看待它,並牢記協會和授權。

協會:在面向對象的編程中,關聯定義了允許一個對象 例如導致另一個代表其執行的操作對象的類之間的關係 。

委託:委託允許對象的行爲爲 根據另一個對象的行爲定義。術語 「代表團」,是指責任的代表團。主要 重點代表團是消息傳遞的其中一個對象可能的消息 委託責任無法處理的對象 潛在可能(其代表)。

那麼,如果我們設計我們的用戶和角色就像這樣。沒有角色等級和用戶不繼承或專注某一類(藝術家,管理員),而不是所有的(角色)類包含用戶對象和委託。我想到的是使用Rails實現的方式和方法是這樣的:

class User < AR::Base 
    def user_method 
    end 
end 

class Artist < AR::Base 
    has_one :user 

    def artist_method 
    # perform an admin task 
    end 
end 

class Admin < AR::Base 
    has_one :user 

    def admin_method 
    # perform an admin task 
    end 
end 

role class model由弗朗西斯·莫斯在他的文章中描述建模角色。

1

這是基本的設置,爲declarative authorization寶石,我使用。但是,如果您的授權要求不超過要求用戶擁有的角色類型,您可以直接使用它。

它確實需要一個roles表,這樣,因此這可能不是真的是你的幻想。

class Role < ActiveRecord::Base 
    belongs_to :user 
end 

class User < ActiveRecord::Base 
    has_many :roles 

    def role_symbols 
    roles.map { |r| r.title.to_sym } 
    end 

    def admin? 
    has_role?(:admin) 
    end 
    # include more role booleans or write some ruby magic to be DRY 
    # ... 

    def has_role?(r) 
    role_symbols.include?(r.to_sym) 
    end 
end 

# give or take 
user = User.new 
user.roles << Role.new :title => "admin" 
user.roles << Role.new :title => "artist" 

user.role_symbols # => [:admin, :artist] 
user.admin? # => true 
user.has_role?(:artist) # => true 
0

您可以有兩個模型用戶和角色。和角色屬於用戶。

指定角色模型的用戶角色(如管理員,版主)。在AR