【问题标题】:Rolify make association to a user with a specific roleRolify 与具有特定角色的用户建立关联
【发布时间】:2020-07-25 22:10:49
【问题描述】:

我想建立一个关联,其中一个用户有很多交易,一个交易属于一个用户以及另一个具有角色(“关联”)的用户。

我正在使用rolify gem 来执行此操作。

像这样:

# user.rb

has_many :deals
# deal.rb

belongs_to :user
belongs_to :associate # User with role 'associate or admin'

第一个属于可以是任何用户,不管该用户是任何角色它仍然应该工作,第二个属于但绝对应该是一个员工或管理员

你认为我应该为此使用 rolify 吗?还是我不应该为每个角色制作不同的模型?

更新

我当前的解决方案不起作用,因为作为关联的用户需要两个关联,即有很多交易和has_many :client_deals。我还不确定命名。

更新 2

Max 的解决方案效果很好!

【问题讨论】:

    标签: ruby-on-rails rolify


    【解决方案1】:

    这不是您想使用 Rolify 表格的地方。 Rolify 通过roles 表在角色和资源之间创建一对一的关联。然后角色通过users_roles 表与用户建立多对多关联。

    这意味着它适用于关联是一对多或多对多的情况,但由于缺少数据库,Rolify 确实不能保证永远只有一个具有特定角色的用户约束。

    即使您添加了验证或其他应用程序级别的约束,仍然存在可能发生争用条件的可能性,这些条件可能只需双击即可。

    相反,您只想创建单独的一对一关联:

    class Deal < ApplicationRecord
      belongs_to :creator, 
        class_name: 'User',
        inverse_of: :created_deals
      belongs_to :associate, 
        class_name: 'User',
        inverse_of: :deals_as_associate
    
      validates :must_have_associate_role!
    
      private
      def must_have_associate_role!
        # this could just as well be two separate roles...
        errors.add(:associate, '^ user must be an associate!') unless associate.has_role?(:associate)
      end
    end
    
    class User < ApplicationRecord
      has_many :created_deals, 
        class_name: 'Deal'
        foreign_key: :creator_id,
        inverse_of: :creator
      has_many :deals_as_associate, 
        class_name: 'Deal'
        foreign_key: :associate_id,
        inverse_of: :associate
    end
    

    只要每个关联的名称是唯一的并且您使用 class_nameforeign_key 选项正确配置,两个模型之间实际上可以有无限数量的关联。

    由于这使用单个外键,这意味着 ere 永远只能是一个,并且您可以免受竞争条件的影响。

    【讨论】:

    • 在我的用例中,我需要管理员也能够作为员工参与,您对此有何看法errors.add(:associate, '^ user must be an associate or admin!') unless associate.has_role?(:associate) || associate.has_role?(:admin)
    • 或者我可以让所有管理员也分配给他们的关联角色
    • 您应该能够通过单个查询来做到这一点。我不记得有没有has_role?可以获取角色列表,但请查看文档。
    • 是的User.with_any_role(:associate, :admin)
    【解决方案2】:

    对于关联,您可以使用以下内容

    belongs_to :associate, -> { includes(:roles).where(roles: {name: ['associate', 'admin'] }) }, class_name: 'User', foreign_key: 'user_id'
    

    【讨论】:

    • 这甚至应该完成什么?
    • @max,当用户角色为 Associate 或 admin 时,我以为他正在尝试与 Associate 建立关联。
    • 如何实现这一目标?您只是添加了一个不执行任何操作的外部联接。
    • 在这种情况下,如果该员工不是管理员或员工,则 deal.associate 将为 nil。好的,我知道了 。可能我错误地解释了这个问题。当用户的角色是管理员或助理时,我认为助理将属于交易
    猜你喜欢
    • 1970-01-01
    • 2021-09-13
    • 2012-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多