【问题标题】:Rails: complicated design choice: polymorphism? STI?Rails:复杂的设计选择:多态?性病?
【发布时间】:2011-10-26 19:18:03
【问题描述】:

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

背景:

我有一个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 和用户类型之间的模型?

有什么意见吗?

【问题讨论】:

  • 请注意,建议进行编辑,将您对“身份验证”一词的使用更改为“授权”。我相信更正是准确的,但在这种情况下,IMO 最好由您决定。
  • (我还要补充一点,您之前的明显相关问题改变了这个问题的性质及其最佳答案。也就是说,我仍然不确定有什么大不了的——如果你想从一个表单创建用户,这不是很多额外的工作,你知道吗?)
  • 我正在考虑链接到我以前的问题。但是,这个问题对应用程序需要做什么有更准确和准确的描述。如果可以,我会扔掉旧的。另外,您是指我在用户模型的描述中使用“身份验证”一词吗?用户模型中没有授权(还)。感谢您的 cmets!
  • 我认为原编辑只是指出,如果有身份验证,这无关紧要,讨论的重点是授权,仅此而已。

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


【解决方案1】:

我真的认为您不需要 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

【讨论】:

  • 我在等待答案的同时开始实施这个解决方案,我很高兴听到其他人(不仅仅是一个人)建议这条路线。这绝对是要走的路。我不能只结束管理员吗?买家?和卖家?方法转换为一个检查用户角色的 is_a?(role) 方法?类似于 Ryan Bates 在他的 CanCan Railscast 中的做法。
  • 当然。我喜欢不提供参数的直接方法的简单性。
  • 太棒了,谢谢!关于通过批量分配保护管理员角色的任何建议?我希望用户选择他们的角色,但仅限于买家和卖家。这可能吗?
【解决方案2】:

到目前为止,您似乎有一个指示其用户类型的标志,或者一个具有字符串类型的列等。

您没有指出任何依赖于此的行为——没有出现在列表等中可以使用范围来处理。管理员可以用一个标志来处理。

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

【讨论】:

    【解决方案3】:

    第三个选项。

    ...买家应该可以选择更改他们的帐户类型并成为 一个卖家。同样,卖家可以更改他们的账户类型和 “停用”他们的卖家账户,将他们从 卖家。

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

    【讨论】:

    • 我其实想了很多,决定不走这条路。感谢您的评论!
    猜你喜欢
    • 2017-07-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
    相关资源
    最近更新 更多