Rails:复杂的设计选择:多态? STI?

时间:2011-10-26 19:18:04

标签: ruby-on-rails ruby-on-rails-3

我在设计这个应用程序时一直在尝试不同的技术,对我来说非常复杂,因为有很多解决方案可供选择。决定哪些解决方案是最好的,这已成为我过去几周的全职工作。

背景:

我有一个User模型,其中包含一些非常基本的身份验证功能。该应用程序将有三种不同类型的用户;管理员,买家和卖家。用户类型将在注册期间确定,其中复选框将询问用户是否是卖家。如果选中此框,则用户是卖家,如果未选中该框,则认为他们只是买家。我宁愿没有下拉菜单来选择用户类型(买方,卖方)。很容易到目前为止。

详细说明:

卖家有个人资料,访问该网站的用户将能够浏览不同的卖家并查看他们的个人资料。买家没有个人资料,不应列在网站上供用户查看。如果这不够复杂,买家应该可以选择更改帐户类型并成为卖家。同样,卖家可以更改其帐户类型并“停用”其卖家帐户,将其从卖家列表中删除。

设计选项:

单表继承

尝试使用STI实现此功能时,我想到的并不是最理想的。我面临两个选择:一个凌乱的控制器,根据上面提到的复选框(一个控制器 - UsersController)决定创建什么类型的用户,或两个不同的注册表单相同(两个控制器 - BuyersController) ,SellersController)。

has_one或“has_none”个人资料关联

class User < ActiveRecord::Base
  has_one :profile # only if the user_type or role is "seller"
end

class Profile < ActiveRecord::Base
  belongs_to :user
end

在这里,我将使用CanCan或declarative_authorization之类的东西,让用户通过上面提到的复选框选择他/她的角色。这会带来安全风险,因为会有一个管理员角色,我不希望这个用于批量分配。

我想无论你看哪种方式,我都会有一个凌乱的控制器,其中有关于如何创建用户的条件。除非我选择两个复选框(“我是卖家”和“我是买家”),但这似乎是多余的。似乎无论我选择哪种设计,我都会遇到一些破解的解决方案。

或许介绍一些介于User和用户类型之间的模型?

有什么意见吗?

3 个答案:

答案 0 :(得分:3)

我真的认为你不需要STI或多态性。单个用户模型就足够了。我会为您的用户模型添加三种方法(管理员?,买家?,卖家?),并添加仅返回买家,仅卖家或仅返回管理员的范围。

在您的情况下,听起来您的用户角色数量非常少(现在有2个,管理员扩展到3个)。我可能会使用Ryan在"Embedded Associations" Railscast中讨论的技术。

我在我的最新项目中做了一些非常相似的事情,然后使用CanCan(在我的情况下,2.0 alpha分支,因为我发现它更简单)。你的能力类看起来像这样(在2.0语法中,但你可以用1.x做同样的事情,我敢肯定)

class Ability
  include CanCan::Ability

  def initialize(user)
    if user.seller?
      can :create, :profile
    else
      ...
    end
  end
end

答案 1 :(得分:1)

到目前为止,听起来你有一个标志表明他们的用户类型,或者一个字符串类型的列等。

您尚未指明任何依赖于此的行为 - 未在列表中显示等等,可以使用范围进行处理。管理员可以用旗帜处理。

我还没有看到问题,至少不是几周的问题。

答案 2 :(得分:0)

第三种选择。

  

...买家应该可以选择更改自己的帐户类型并成为   卖家。同样,卖家可以更改其帐户类型和   “停用”他们的卖家帐户,将其从列表中删除   卖家。

您是否考虑过不允许转换帐户?如果买家想成为卖家,那么他们会创建一个新的“卖家”帐户。卖方与买方的情况相同。这意味着有两个控制器用于注册等,但它会保持你正在寻找的分离。如果两者必须互相排斥,您可以进行基本的电子邮件检查以验证用户是否还没有帐户,如果有,则必须在创建新帐户之前取消激活现有帐户。