【问题标题】:Ruby on Rails - Dividing a Class into multiple classesRuby on Rails - 将一个类分成多个类
【发布时间】:2023-02-10 20:53:49
【问题描述】:

我有这个应用程序:任务管理器。

我有一个User

  • 一个用户可以创建一个或多个Groups -> 然后就变成了行政它创建的组
  • 同时一个用户可以只是另一个创建的组的Member(用户和组之间的中间表)。

所以我有那个用户:

has_many :groups, foreign_key: :admin_id, dependent: :destroy
has_many :groups, through: :members

现在我想问 Db:

  • 给我用户是管理员的组
  • 给我用户只是一个用户的组

我很可能会为此创建一个 SQL 查询,但我认为会有更多的 Rails 做事方式。

有没有办法做到这一点?我只能想到拥有 User 但同时将其分为 2 个不同的子类,如 UserAdmin 和 NormalUser。但是我不确定该怎么做,或者这是否是正确的方法。

先感谢您!

【问题讨论】:

  • 带有user_idgroup_idrole 的中间模型(您似乎已经有一个member 表)怎么样。后者可以是 'member''admin' 以指定用户在该组中的角色。这样,您只有一个表可以查询,并且每个组可以轻松地拥有多个管理员(至少在技术上)。

标签: ruby-on-rails ruby class


【解决方案1】:

将您的用户类拆分为多个类并不是您希望用户能够在不同组中担任不同角色的答案。相反,几乎没有不同的解决方案。

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 或从头构建基于角色的访问系统的教程。

【讨论】:

  • 请注意,我有意使用了membership 而不是member
猜你喜欢
  • 1970-01-01
  • 2019-04-13
  • 1970-01-01
  • 2015-03-02
  • 1970-01-01
  • 2015-12-18
  • 1970-01-01
  • 1970-01-01
  • 2011-01-02
相关资源
最近更新 更多