ruby-on-rails – Rails:PolyMorphic或STI或用户管理的其他东西?

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – Rails:PolyMorphic或STI或用户管理的其他东西?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我一直在撞墙试图绕过这头,所以任何指导都会非常感激……

我想要一个用户系统设置来反映以下层次结构:

User
|- email address
|- password
|- billing information
|- contact information
|- account preferences
|
|=> Agent
|=> - agent-specific information
|=> - has_many Users
|=> - belongs_to Manager
|
|=> Manager
|=> - manager-specific information
|=> - has_many Agents,Users
|
|=> Administrator
|=> - can manage everything

我已经有一个用户模型,其中设置了DeviseCanCan以处理身份验证和授权,因此我知道如何使用角色将用户类型限制为特定操作,等等.

我失去的是如何在我的Rails代码数据库中组织这些子类关系.从上面可以看到,Agent,Manager和Administrator都共享User中包含的信息,但每个信息都有与之关联的附加功能和信息.

我读过一些关于STI,polymorphic associationsself-referential associations内容.

如果我使用STI,那么User表必须包含我所有[Agent / Manager / Administrator]特定信息的字段,对吧?这会让我的用户表变得庞大,这是我想避免的.相反,如果我使用多态,那么我不必在所有其他类型的User子类表中复制User中的所有公共信息吗?

并且为了增加我的困惑,我无法理解上述问题的答案如何与子类之间的关系一起工作(例如,一个Manager has_many Agents,但两者都是User的子类……? ?).

我真的很感谢有人通过一个详细的答案让我直截了当,该答案适当考虑了代码的可读性和数据完整性,这简单地解释了(好像是一个Rails新手)为什么A是最好的方法,为什么B或n是 – 通过比较 – 对于这种情况不是一个好的方法,并且提供了实现上述关系的示例代码.我想解决这个问题,但更重要的是,我想了解解决方案的工作原理!

解决方法

我认为没有一个简单的解释为什么任何方法在任何情况下都是最好的.关于Stack Overflow的大量问题是关于如何设计模型之间关系的问题.这是一个复杂的主题,正确的解决方案需要对您正在解决的问题有深入的了解.即便如此,你可能也不会在前几次做对.

到目前为止,最好的方法是在这个问题上完全使用TDD / BDD,让测试/规格驱动你的设计.并且不要害怕重构你是否找到了更好的方法.大多数时候,只有在尝试了几个错误解决方案之后才能看到正确的解决方案.你会了解边缘情况.正如沃德·坎宁安(Ward Cunningham)在其“技术债务”(Technical Debt)中所说的那样:“事后重构就好像你从一开始就知道自己在做什么”.尽管如此,请务必进行验收测试以验证其行为.

更具体地解决您的问题.还有第三个选项,即完全拆分类,每个类都有自己的表.我在我目前的项目中尝试过,我喜欢它.如果在您的业务领域中没有意义,则无需定义类似用户内容.如果他们有共享行为,请使用mixins.最重要的警告是让他们再次通过相同的表单登录并不是直截了当的.

我有管理员,招聘人员,供应商和Visistor模型.它们都是独立的模型,与mixin共享一些行为.他们都有自己的命名空间控制器来行动.例如,管理员的所有操作都在Backend命名空间中.还有一个名称空间的ApplicationController. Backend :: ApplicationController只是指定before_filter:authorize_admin!.没有转换,没有复杂的案例陈述,没有.

你需要特别注意约定.如果您在模型中使用相同的名称,您的mixins可以变得非常简单.阅读ActiveSupport :: Concern以使mixins更易于使用.我有这样的mixin:

module Account
  extend ActiveSupport::Concern
  included do
    devise :database_authenticatable,:trackable,:recoverable,:rememberable
  end
end

在我的路线:

devise_for :recruiters
devise_for :suppliers
# etc...

app / controllers / backend / application_controller.rb看起来像这样:

class Backend::ApplicationController < ::ApplicationController
  layout "backend"
  before_filter :authenticate_admin!
  def current_ability
    @current_ability ||= AdminAbility.new(current_admin)
  end
end

所以,总结一下.任何架构都可以. STI和多态性有其自己的位置,但一定要根据您的域建模您的架构. Ruby是一种非常灵活的语言,您可以利用它来获得优势. Devise和CanCan是出色的宝石,可以轻松应对这些情况.我向您展示了我正在进行的项目的解决方案.它适用于我,但我不能说它是否适合你.当你觉得自己做出了错误的决定时,不要害怕尝试和重构,而不是继续修补你原来的想法.

PS.说到STI和关系:它们也很好地协同工作.您可以定义从一个子类到另一个子类的关系.它将按预期工作.

猜你在找的Ruby相关文章