2011-09-03 6 views
6

私はレールが新しく、私は2番目のレールアプリに取り組んでいます。ユーザーのためのレールモデル構造

アプリの役割はユーザーごとに異なりますが、ユーザーによっては複数の役割があります。

サイトのすべてのユーザーはアーティストになります。一部のユーザーにはモデレーターの役割があります。

どうすればこの構造になりますか?私が使用したPHPアプリケーションでは、ユーザーが1人しかなく、is_adminなどのデータベース列があります。しかし、私はRailsアプリケーションのソースを見てきましたが、UserとAdminなどの別々のモデルを見ました。なぜわからないのですか?

私は、モデレータである可能性のあるロール属性を持つ単一のUserモデルを持っていて、ビュー、ルートなどでUsers "Artists"を呼び出すだけですか?

ユーザーモデル、それを継承するモデレーターモデル、およびbelongs_to Userというアーティストモデルが必要ですか?

私は本当に混乱しています。

答えて

7

宝石DeviseとCanCanを探すことができます。このペアは本当に強力な組み合わせです。これにより、UserとRoleの2つのモデルが作成されます。役割では、新しいモデルを作成することなく、新しい役割を作成できます。モデル能力を作成しますが、ここでは役割のアクセスルールを定義できます。

マニュアル:ここ 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

私のモデルは、このようになります。必要であれば

class YourController < ApplicationController 
    before_filter :authenticate_user! 
    load_and_authorize_resource 

    ... 

end 
+0

これは私の提案でした。このアプローチについて私が気に入っているのは、残りのアプリケーション・ロジックからビジネス・ポリシーを分離することです。 –

+0

はい、この分離は良い、柔軟な能力を与えます。私は1つのプロジェクトで開発者が非常に不快な認証システムを作りました。そこでは新しい役割と能力を追加するために各コントローラとモデルに多くのコードを書く必要がありました。私はDeviseとCanCanをインストールして設定するために、古いシステムを削除して2時間近くを費やすのに多くの時間を費やしています。今私は幸せです。そして私が自由な時間を過ごす時、私は役割と能力を管理するためのユーザーインターフェイスを書くつもりです。これらのシステムでは、この作業は簡単になりました。 –

+0

これはいくつかのアプリケーションでこれを使用しましたが、devise-cancanのミックスも「ベスト・オブ・ブリード」のアプローチになっています。認証/承認の今年の標準として、多くの組織で急速に採用されています。 –

2

それぞれに特定のフィールドがないため、異なるモデルを作成する必要はありません。したがって、各ユーザーの「役割」を設定するだけで済みます。 2つのオプション:ロールテーブルを作成するか、ユーザーテーブルにロールフィールドを追加します。両方のソリューションが機能し、2つ目のソリューションは柔軟性は向上しますが、最適化されません。

しかし、特定のケースでは、複雑な役割管理をしていないため、より簡単なソリューションを見つけることができます。すべてのユーザーがアーティストである場合は、コード内でこれを指定する必要はありませんが、ユーザーが何であるかの暗黙の説明に含まれています。したがって、ユーザーが管理者であるかどうかを保存する必要があります。最高の解決策はブール値フィールド "is_admin"を作成することです。

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

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

そして、あなたはそのような単純な要求を持つことができます:その後

あなたはそのように、あなたの保護されたコントローラーで、いくつかのbefore_filterを作成する必要があります

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

あなたがより多くを探している場合をあなたはこの小さな宝石をチェックすることができます:https://github.com/ryanb/cancan

しかし、私はそれが今の場合ではないと思う。簡単な問題がある場合は、簡単な解決策を探してください!

+1

ブール値は条件式に最適な 'foo?'メソッドを生成し、Rubyは 'あれば'の形でより良い 'if not'を持っています。それらを組み合わせる: 'redirect_to:root current_user.is_admin? ' – coreyward

+0

ActiveRecordヘルパーの良い発言、私はそれを知らなかった!単純なソリューションの場合は –

+0

+1です。 Rubyについての素晴らしい点は、別のロールモデルなどに変更するときにブール値フィールドを使用し、 'is_admin? 'インターフェイスを保持できることです。 –

2

:あなたが唯一のこの2行を追加する必要がありますコントローラで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 

特定の役割や管理者などのコードを持っている他のすべてのクラスが継承する基本Userモデルを作成することです。その後、Userモデルから継承したAdminクラスとModeratorクラスを作成できます。これは、コード内のユーザーの役割を常に確認することを避けることができます。 current_user.do_some_admin_thing if current_user.is_admin?。あなたのクラスはUserクラスは、最も基本的な権限を持っている、モデレーターは、ユーザーがプラスモデレータ特定の方法および管理者は、ユーザーとモデレータができることはすべてプラス管理者の特定を行うことができ、すべてを行うことができます。この例では、この

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

質問を編集して、これがシングルテーブル継承を使用しており、公式のレール文書にリンクしていることを明示してください。 –

+0

質問は、異なるユーザーのための異なる動作については言及していません、異なるものを行うための異なる認証だけです。 Userモデルのインスタンスが実際に異なる動作をしない限り、異なるサブクラスを作成することは非常に複雑です。継承の過度使用は反パターンです。 – Winfield

1

私はDeviseとCanCanの組み合わせが強力で機能することに同意しますが。アソシエーションと代表団を念頭に置いて別の視点で見てみましょう。

協会:オブジェクト指向プログラミングでは、アソシエーション1つのオブジェクト インスタンスが別のは、その代わりにアクションを実行させることを可能にするオブジェクトのクラス間 関係を定義します。

委任:委任によって、オブジェクトの動作を別のオブジェクトの動作に関して定義した にすることができます。 「委任」という用語は、責任の委任を指します。プライマリ 委任の強調は、オブジェクトが メッセージの責任を委譲する可能性がある(その代理人)可能性のあるオブジェクト にメッセージを渡すことにあります。

これで、このようなユーザーとロールを設計するとどうなりますか?ロールクラスはなく、ユーザは特定のクラス(Artist、Admin)を継承または特殊化するのではなく、すべての(Role)クラスにUserオブジェクトとdelegateが含まれています。私が考えと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は、モデルの役割に彼の記事にフランシスG.Mosséによって記述されています。

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

ユーザーとロールの2つのモデルを使用できます。そしてロールはユーザーに属します。

ロールモデルでユーザーの役割(管理者、モデレータなど)を指定します。

関連する問題