【问题标题】:Arranging my classes rails mongoid安排我的课程 rails mongoid
【发布时间】:2016-05-16 18:17:02
【问题描述】:

我有 4 种用户类型

-SuperAdmin
-Admin
-Manager
-Tenant

我目前有 2 个连接器类

-manager_approval
-reportapproval

租户创建并拥有 Report 类。

我需要确保管理员、超级管理员、经理和租户可以访问 Tenants.report 的实例

目前我有以下设置,但我不确定这是否正确

class SuperAdmin
 include Mongoid::Document

 has_many :admins
 has_many :managers
 has_many :reports
end

class Admin
  belongs_to :super_admin
  has_many :manager_approvals, dependent: :destroy
  has_many :managers
  has_many :reportapprovals
  has_many :reports
end

class belongs_to :admin
  has_many :tenants
  has_many :reports
  has_many :reportapprovals, dependent: :destroy
  has_many :coupons
  has_many :manager_approvals, dependent: :destroy
end

class Tenant
 include Mongoid::Document

 has_one :report, dependent: :destroy
 has_one :tenant_record, dependent: :destroy, autosave: true
 has_many :reportapprovals, dependent: :destroy, autosave: true
 has_many :managers
end

class Reportapproval
  include Mongoid::Document

  belongs_to :tenant, inverse_of: :reportapprovals
  belongs_to :manager, inverse_of: :reportapprovals
  belongs_to :admins
  has_many :reports, dependent: :destroy
  belongs_to :manager_approvals
end

class ManagerApproval
 include Mongoid::Document

 belongs_to :admin, inverse_of: :managers, dependent: :destroy
 belongs_to :manager
 has_many :reportapprovals
 has_many :reports
end

class Report
 include Mongoid::Document

 belongs_to :tenant, dependent: :destroy
 has_and_belongs_to_many :reportapprovals
 has_and_belongs_to_many :managers, through: :reportapprovals
 has_many :admins, through: :managers
end

我觉得这不对,希望有人对其进行审核。最终,报告由租户创建,经理可以访问报告,管理员可以访问经理可以访问的所有报告,超级管理员可以访问所有经理的所有报告。感谢您的帮助!

【问题讨论】:

    标签: ruby-on-rails associations mongoid


    【解决方案1】:

    单一集合继承

    使用继承,以便将不同类型的用户塞入同一个集合中:

    class User
      include Mongoid::Document
    end
    
    class Admin < User
    end
    
    class SuperAdmin < User
    end
    

    在 SQL 世界中,这就是所谓的单表继承。 MongoDB 的无模式特性消除了 STI 的许多缺点,使其成为一个非常强大的工具。

    这将让您查询所有用户类型:

    User.where(name: 'Bob') # returns any subtype
    

    或特定类型的用户:

    Admin.where(name: 'Bob') # returns only documents with the class Admin.
    

    在处理可能只知道用户 ID 而不知道类型的授权时,这一点尤其重要。

    让他们滚动

    虽然拥有一个 User 类和一个 Admin 类(等等)并设置一个具有升级权限的复杂类树似乎是一个合理的想法,但它很少能很好地适应现实。并且有不少缺点:

    • 当用户被提升甚至降级时,您如何处理?
    • 如果用户属于多个类别怎么办?

    请考虑使用带有用户和角色的tried and true pattern,它允许大量可扩展性。例如,您可以将角色限定到特定资源或创建角色层次结构。

    class User
      include Mongoid::Document
      embeds_many :roles
    
      def has_role?(role)
        self.roles.where(name: role).any?
      end
    
      def admin?
        has_role? :admin
      end
    
      def admin!
        self.roles.find_or_create_by!(name: :admin)
      end
    end
    
    class Role
      include Mongoid::Document
      embedded_in :user
      field :name, type: Symbol
    end
    

    请注意,由于在类上声明关系的方式而不是每个实例,基用户类将包含所有关系:

    class User
      include Mongoid::Document
      embeds_many :roles
    
      # ...
      has_many :reports
      has_many :report_approvals
    
      # ...
    end
    

    虽然有可能在运行时将其添加到实例中,但它看起来很 hacky。

    【讨论】:

    • 另外你在命名时应该保持一致 - Reportapproval 应该是ReportApproval - report_approval
    • 很好的答案!因为正如您所说,并非该类的每个实例都将具有相同的权限,所以我认为角色可以很好地确定实例。
    • 一个问题,对于单表继承,每个用户的逻辑是否仍然进入其自己的文件,而固有逻辑进入每个文件,或者它们只是所有用户的一个文件和继承逻辑在那个文件的顶部?
    • 我不太确定你在问什么。为了让 Rails 自动加载正常工作,您可以将每个模型类放在自己的文件 /app/models/admin.rb/app/models/super_admin.rb
    • 对,它只是普通的旧继承。您在User 类中添加的任何字段或关系都将渗透到子类中。 Mongoid 只是将文档放在 users 集合中,因为那是 include Mongoid::Document 所在的位置。 rohitrox.github.io/2013/08/30/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多