Ruby on Rails 中的多个用户角色
Posted
技术标签:
【中文标题】Ruby on Rails 中的多个用户角色【英文标题】:Multiple user roles in Ruby on Rails 【发布时间】:2011-05-31 21:21:24 【问题描述】:我正在构建一个具有四种不同用户类型的库存管理应用程序:管理员、员工、制造商、运输商。我还没有开始编码,但这就是我的想法。制造商和运输商与 has_many 相关:通过与产品的多对多关联如下:
class Manufacturer < ActiveRecord::Base
has_many :products
has_many :transporters, :through => :products
end
class Product < ActiveRecord::Base
belongs_to :manufacturer
belongs_to :transporter
end
class Transporter < ActiveRecord::Base
has_many :products
has_many :manufacturers, :through => :products
end
所有四种用户类型都可以登录,但是他们会有不同的权限和视图等。我不认为我可以将它们放在同一个表(Users)中,但是,因为他们会有不同的要求,即:供应商和制造商必须有帐单地址和联系信息(通过验证),但管理员和员工不应该有这些字段。
如果可能,我希望有一个登录屏幕,而不是 4 个不同的屏幕。
我不是要求确切的代码来构建它,但我无法确定实现它的最佳方法。任何想法将不胜感激 - 谢谢!
【问题讨论】:
【参考方案1】:您的基本方法似乎是合理的。我建议您创建一个 User 基类并将 STI 用于特定的 User 类型,例如:
class User < ActiveRecord::Base
end
class Manufacturer < User
has_many :products
has_many :transporters, :through => :products
end
...等等。这样,如果需要将多个用户类型聚合到一个关系中,而不管类型如何,您就可以使用一张表来描述一般的用户。这是一种相当普遍的方法。
根据不同用户对系统的访问权限,您可能需要查看角色管理 gem,例如 Declarative Authorization。
【讨论】:
感谢您的帮助!如何为此设置数据库表,以及特定用户类型的用户和 STI 基类?我真的,真的是 Rails 的新手 :) 数据库中只有一个“用户”表。 STI/单表继承使用基表中的“类型”字段(在本例中为“用户”)来区分基类的子类型。您需要在迁移中添加此字段。然后,基类的所有子类型的所有属性都将保存在 users 表中,即使其中许多属性不会被特定实例/行使用。这是使用 STI 模式的权衡——您可能有许多空字段用于未使用的属性,具体取决于有多少特定于子类型的属性。【参考方案2】:对于多用户系统,通常首选的方法是 - 使用角色模型或 STI。如果您的用户可以同时拥有多个角色,例如单个用户是制造商和运输商,那么角色库系统将是一个很好的解决方案。如果用户角色是固定的,那么我认为你应该选择 STI。
【讨论】:
【参考方案3】:我建议你创建一个 User 模型、Address 模型、ContactInfo 模型等。你不应该在 User 模型中有这些类型的字段。规范化数据库。在 User.id 的其他每个类中都有一个 FK。
如果您必须将它们分开,则规范化登录并使其多态以引用其所有者(制造商、员工等)
【讨论】:
Weeeell...也许吧。拥有一个地址表当然是标准化的,但在现实世界中很多时候它是矫枉过正的,事实上,即使是最顽固的标准化怪胎也经常会承认像地址这样的东西——在大多数情况下,这只不过是而不是 varchar 字段——不需要将所有开销归一化到它自己的表中。你真的想要一个 SQL 连接命中永远的用户查询吗?对于这样一个简单的操作,性能不是很好。这在很大程度上取决于域,以及地址是否真正复杂和可重用等。 @Dave Sims - 我完全不同意。在当今世界,我们需要尽可能多的信息。规范化(尤其是地址)允许未来扩展——我们可以允许用户拥有多个地址(例如家庭和工作)。而且,无论是 SELECT * 返回 10 列还是 JOIN 返回 10 列,都无关紧要(就像对于非常大的数据集来说,开销实际上是微不足道的)。此外,您不会总是向用户显示地址,那么为什么要将它放在用户表中呢?这是一个单独的对象 @Dave Sims - (续)。我是这样看的。我有名字,我有姓氏。我也有地址。我没有 address_line_1 和 address_line_2、zip...,一个地址有一个 address_line_1、2..zip 等。对我来说,将这些东西分开更有意义。你可以有一个没有地址的用户吗?如果有人无家可归,您真的想限制对您网站的访问吗?我说得太夸张了,但我想你会明白为什么规范化很重要。 @seth.vargo:这很好地说明了标准化的众所周知的好处,但您也必须承认这些好处的代价可能对每个应用程序都没有意义。过度标准化可能是早期优化的一种情况。在“当今世界”中,我们已经看到,对每一位相关数据都有一个 fk 既是一种好处,也是一种责任。 Mongo 等框架的兴起表明,对于许多应用程序和域而言,规范化不是主要关注点,性能是可以用简单的树结构而不是复杂的关系结构表示数据的主要问题。 @seth.vargo:至于您对连接性能的断言——嗯,您是否真的需要优化现实世界的生产查询?优化的首要规则之一是限制您加入的表的数量(在可能的情况下),我向您保证,在“当今世界”,这绝不是一个无关紧要的问题。至于你那可怜的无家可归者——伙计,我不知道正常化与这有什么关系。您可以有一个必需/非必需字段或必需/非必需 fk/pkid,在架构级别、应用程序级别或两者强制执行。以上是关于Ruby on Rails 中的多个用户角色的主要内容,如果未能解决你的问题,请参考以下文章