将您的用户类拆分为多个类并不是您希望用户能够在不同组中担任不同角色的答案。相反,几乎没有不同的解决方案。
1.增加外键列
如果你想在用户和组之间建立特定的 1:1 关联,你可以添加一个单独的关联:
class AddCreatorToGroups < ActiveRecord::Migration[7.0]
def change
add_reference :groups, :founder, null: false, foreign_key: { to_table: :users }
end
end
class Group
# ...
belongs_to :founder,
class_name: 'User',
inverse_of: :groups_as_founder
end
class User
# ...
has_many :groups_as_founder,
class_name: 'Group',
foreign_key: :founder_id,
inverse_of: :founder
end
如果您需要能够非常高效地预先加载组和那个用户,这是一个好主意。这可以与其他选项结合使用。它不会解决您要将多个管理员分配给一个组的情况。
2.将角色添加到成员资格
class AddCreatorToGroups < ActiveRecord::Migration[7.0]
def change
add_columns :memberships, :role, :integer, default: 0
end
end
class Membership < ApplicationRecord
enum :role, {
normal: 0,
admin: 1
}
end
class Group
has_many :normal_memberships,
class_name: 'Membership',
-> { Membership.normal }
has_many :admin_memberships,
class_name: 'Membership',
-> { Membership.admin }
has_many :normal_members,
class_name: 'User',
through: :normal_memberships
has_many :admin_members,
class_name: 'User',
through: :admin_memberships
end
class User
has_many :normal_memberships,
class_name: 'Membership',
-> { Membership.normal }
has_many :admin_memberships,
class_name: 'Membership',
-> { Membership.admin }
has_many :groups_as_normal_member,
class_name: 'Group',
through: :normal_memberships
has_many :groups_as_admin_member,
class_name: 'Group',
through: :admin_memberships
end
这是一个大大简化的示例,其中可用角色是通过成员资格表上的枚举定义的。通过遍历 Membership.roles.key 可以在一定程度上避免这种重复。
3.独立的角色系统。
另一种替代方法是使用单独的系统(如 Rolify)和一组完全不同的表来存储组中的角色。如果您搜索一下,有很多关于如何使用 Rolify 或从头构建基于角色的访问系统的教程。