首页 > 解决方案 > 使用 Rolify/Devise/Cancancan 与角色关联

问题描述

我在某处读到使用 Rolify/Devise/Cancancan 是配置两个具有登录功能的设计模型(使用一个登录页面而不是两个)以及它们各自在其他模型之间的关联的更好选择。我对如何在内部设置角色并仍然使用关联感到困惑。例如:

如果我使用了两个 Devise 模型,它们就会...

class Supervisor < ApplicationRecord
  has_many :employees
end

class Employee < ApplicationRecord
  belongs_to :supervisor
end

但是对于 Rolify,我想做以下事情:

  1. 管理员 - 此用户应该能够设置其他用户的角色
  2. 主管 - (例如,此用户可以设置员工时间表)
  3. 员工

我要解决这个问题了吗?我知道这个例子很模糊,我似乎无法在任何地方找到关于如何设置与角色的关联的答案。

标签: ruby-on-railsdeviseassociationscancancanrolify

解决方案


您正在寻找的很可能是自引用关联

class AddSupervisorToUsers < ActiveRecord::Migration[6.1]
  def change
    add_reference :users, :supervisor, 
      null: true, 
      foreign_key: { to_table: :users }
  end
end

class User < ApplicationRecord
  belongs_to :supervisor, 
    class_name: 'User',
    optional: true,
    inverse_of: :employees
  has_many :employees,
    class_name: 'User',
    foreign_key: :supervisor_id,
    inverse_of: :supervisor
end

这基本上只是一个指向同一张表的关联。请注意,外键列必须可以为空,以避免鸡与蛋的情况,这会阻止您创建任何用户(如果表为空)。

虽然您可以通过以下方式使用 Rolify 执行此操作:

user.add_role(:supervisor, User.first) # add a role
User.with_role(:supervisor, User.first) # query for supervisors

这实际上并不等同,因为没有什么可以阻止多个用户成为用户的主管。您也没有外键来确保引用完整性,因为角色模型中的关联是多态的。

虽然 Rolify 对于某些用例来说是一个很好的工具,但您可能不想将所有业务逻辑都塞进去。


推荐阅读