一般的なロールライブラリ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
しかし、これを見ると、ユーザーを直接ロールに参加させるのではなく、別のテーブルを用意することの明確な利点が実際にはわかりません。
class User < ApplicationRecord
has_many :roles
end
class Role < ApplicationRecord
belongs_to :user
end
別のRoleテーブルを使用すると、「グローバル」ロールを作成して、ユーザーをそのロールに関連付けることができます。
しかし、パフォーマンスヒットと追加の複雑さに対して、ユーザーごとにロールを一意にすることは本当に価値があるのでしょうか。
別のRoleテーブルを使用すると、「グローバル」ロールを作成して、ユーザーをそのロールに関連付けることができます。
しかし、パフォーマンスヒットと追加の複雑さに対して、ユーザーごとにロールを一意にすることは本当に価値があるのでしょうか。
もちろんです。さまざまなユーザーに割り当てることができる事前設定済み/保存済みの役割を持つことの利点は次のとおりです。
一般的なロールライブラリを構築する場合は、RDBMSによるデータ管理の柔軟性が必要になる可能性があります。あなたが作成している多対多の関係はかなり一般的であり、作業するのはそれほど難しくありません。
うーん...ジャンクションテーブル(user_rolesテーブルなど)を使用しても、パフォーマンスへの影響はほとんどありません。ミリ秒未満:これまでのところノイズでは、違いを垣間見ることすらできません。
このジャンクションテーブルは標準の正規化設計であり、非常に推奨されます。管理者の役割がある場合、2番目に提案された方法では、実際にそれを「制御」する方法がありません。誤って「管理者」ではなく「管理者」にした可能性があります。アプリケーションが中断します(さらに悪いことに、ねじ込みにより、間違った人が何かにアクセスできるようになります)。
「admin」ロールが実際に正しいことを確認する唯一の方法は、一意のロールのマスターリストを用意することです。 2番目の提案にはそれがありません。
ジャンクションテーブルを使用して「正しい」方法で実行する理由は本当にたくさんありますが、それらすべてを掘り下げるには、データベースの正規化についてのレッスンを行う必要があります。これは、かなりの幅、深さ、および多くの基本的なトピックのトピックです。
一般に、データベース設計のパフォーマンスの実現可能性を評価する場合、一般的なクエリで結合されるテーブルの数を調べるだけでは不十分です。テーブルに含まれるデータの量も評価する必要があります。数千万のユーザーレコードがあった場合、パフォーマンスについて懸念を抱き始めるかもしれませんが、ほとんどのシステムでは、少なくとも最初はこのユーザー数を気にする必要はありません。
あなたの第二のモデルは私の意見に欠陥があります。役割とユーザーの間に1対1の関係を作成します。つまり、管理者と呼ばれる役割がある場合、その役割を持つことができるユーザーレコードは1つだけです。
2つのオプションがあります。 1つは、最初の図で定義したマッピング/ジャンクションテーブルを使用する方法です。通常、これらのジャンクションテーブルを使用して、2つのテーブル間に多対多の関係を作成します。
これらの両方の質問にTrueと答える場合は、ジャンクションテーブルが必要です。
質問1でFalseと回答した場合は、おそらくUserテーブルのRole ID列に定義された外部キー制約が適切です。これにより、ユーザーからのRolesテーブルとの1対1の関係、およびロールからユーザーへの1対多の関係が得られます。