web-dev-qa-db-ja.com

役割ベースのアクセスシステムのデータベース設計?

一般的なロールライブラリgemのさまざまなデザインを検討しています。

最初は Rolify gemに基づいていますが、has_many through: HABTMの代わりに関係。 HABTMテーブルはActiveRecordで「ヘッドレス」であり、直接クエリすることはできません。これは大きな欠点です。

class User < ApplicationRecord
  has_many :user_roles
  has_many :roles, through: :user_roles
end 

class UserRole < ApplicationRecord
  belongs_to :user
  belongs_to :role
end 

class Role < ApplicationRecord
  has_many :user_roles
  has_many :users, through: :user_roles
  belongs_to :resource, polymorphic: true
end 

Database diagram based off Rolify しかし、これを見ると、ユーザーを直接ロールに参加させるのではなく、別のテーブルを用意することの明確な利点が実際にはわかりません。

class User < ApplicationRecord
  has_many :roles
end 


class Role < ApplicationRecord
  belongs_to :user
end 

Diagram - roles as a join

別のRoleテーブルを使用すると、「グローバル」ロールを作成して、ユーザーをそのロールに関連付けることができます。

しかし、パフォーマンスヒットと追加の複雑さに対して、ユーザーごとにロールを一意にすることは本当に価値があるのでしょうか。

3
papirtiger

別のRoleテーブルを使用すると、「グローバル」ロールを作成して、ユーザーをそのロールに関連付けることができます。

しかし、パフォーマンスヒットと追加の複雑さに対して、ユーザーごとにロールを一意にすることは本当に価値があるのでしょうか。

もちろんです。さまざまなユーザーに割り当てることができる事前設定済み/保存済みの役割を持つことの利点は次のとおりです。

  1. 各ロールはテストできるため、ユーザーに割り当てることには自信があります。
  2. 重複したデータは変更がより困難です。
  3. 既にビルドされている場合、管理者がロールを割り当てるのが簡単になります。レコードは、ロールの詳細を複製する必要なく追加されます。
  4. パフォーマンスのためにデータを構造化することは重要ですが、3つのテーブルを結合することは、微調整するのにそれほど大きな問題ではありません。

一般的なロールライブラリを構築する場合は、RDBMSによるデータ管理の柔軟性が必要になる可能性があります。あなたが作成している多対多の関係はかなり一般的であり、作業するのはそれほど難しくありません。

3
JeffO

うーん...ジャンクションテーブル(user_rolesテーブルなど)を使用しても、パフォーマンスへの影響はほとんどありません。ミリ秒未満:これまでのところノイズでは、違いを垣間見ることすらできません。

このジャンクションテーブルは標準の正規化設計であり、非常に推奨されます。管理者の役割がある場合、2番目に提案された方法では、実際にそれを「制御」する方法がありません。誤って「管理者」ではなく「管理者」にした可能性があります。アプリケーションが中断します(さらに悪いことに、ねじ込みにより、間違った人が何かにアクセスできるようになります)。

「admin」ロールが実際に正しいことを確認する唯一の方法は、一意のロールのマスターリストを用意することです。 2番目の提案にはそれがありません。

ジャンクションテーブルを使用して「正しい」方法で実行する理由は本当にたくさんありますが、それらすべてを掘り下げるには、データベースの正規化についてのレッスンを行う必要があります。これは、かなりの幅、深さ、および多くの基本的なトピックのトピックです。

2
jleach

一般に、データベース設計のパフォーマンスの実現可能性を評価する場合、一般的なクエリで結合されるテーブルの数を調べるだけでは不十分です。テーブルに含まれるデータの量も評価する必要があります。数千万のユーザーレコードがあった場合、パフォーマンスについて懸念を抱き始めるかもしれませんが、ほとんどのシステムでは、少なくとも最初はこのユーザー数を気にする必要はありません。

あなたの第二のモデルは私の意見に欠陥があります。役割とユーザーの間に1対1の関係を作成します。つまり、管理者と呼ばれる役割がある場合、その役割を持つことができるユーザーレコードは1つだけです。

2つのオプションがあります。 1つは、最初の図で定義したマッピング/ジャンクションテーブルを使用する方法です。通常、これらのジャンクションテーブルを使用して、2つのテーブル間に多対多の関係を作成します。

  1. ユーザーは複数の役割を持つことができますか? (真|偽)
  2. ロールには複数のユーザーを割り当てることができますか? (真|偽)

これらの両方の質問にTrueと答える場合は、ジャンクションテーブルが必要です。

質問1でFalseと回答した場合は、おそらくUserテーブルのRole ID列に定義された外部キー制約が適切です。これにより、ユーザーからのRolesテーブルとの1対1の関係、およびロールからユーザーへの1対多の関係が得られます。

2
maple_shaft