Rails STI vs Polymorphic vs Both

时间:2015-02-21 06:49:08

标签: ruby-on-rails polymorphism polymorphic-associations single-table-inheritance sti

我的rails应用程序中有一个Users类。我需要两种类型的用户,1)玩家,2)经理。用户将使用Devise登录并具有相同的基本用户字段。我将有一个联盟模型。对此进行建模的最佳方法是什么? STI似乎不太正确,但不确定Polymorphic是否有效,因为如果两者都管理器<用户&&播放器<用户。管理者唯一真正的角色是管理员角色,例如在联赛中添加/删除球员,设置赛程等。

class League < ActiveRecord::Base
  has_one :manager
  has_many :players

end

class Match < ActiveRecord::Base
  has_and_belongs_to_many :players
  belongs_to :league
end

class User < ActiveRecord::Base
  has_and_belongs_to_many :matches
  has_and_belongs_to_many :leagues
end

class Player < User
  has_and_belongs_to_many :leagues
  has_and_belongs_to_many :matches
end

class Manager < User
  has_many :leagues
end

非常感谢任何有关设置此方法的最佳方法的建议! 对玩家使用STI ActiveRecord正在寻找连接的Player表,但它不存在。

2 个答案:

答案 0 :(得分:3)

STI可以为此工作,但由于用户类型之间的差异基本上是一个表示用户是管理员的标志,因此您只需要用户检查是否允许某些操作。角色可以是独占的也可以是包含的(这样用户既可以是玩家也可以是经理),但是一旦设置完成,您就可以围绕用户拥有的功能塑造界面:

<% if @user.has_role?('manager') %>
  <%= render 'manager_fields' # or manager_page, etc. %>
<% end %>

如何在控制器中处理这个问题取决于你如何通过Pundit,CanCanCan等宝石实现角色,或者通过对自己编写的内容进行明确检查。 gems将为您提供辅助方法,以减少视图中涉及的键入量,并在后端使用更具声明性的语法。

答案 1 :(得分:1)

STI消除了每个类的单独表的需要,因为大多数(或理想所有)属性在两个模型之间共享。
在这种情况下,我们在名为type的用户表中添加一个新列,该列将指示将对此记录进行解析的类,因此PlayerManager
至于模型

class Player < User

class Manager < User

对于权限,您可以检查用户实例的类型是Player还是Manager

当然,如果你不想做,你不需要做STI,而是你要创建两个表playersmanagers,而你&#39;我需要使用User模型加入它们,这将是棘手的,因为并非所有用户都有管理员而且并非所有用户都有玩家,因此除非您创建多态关系,否则其中一个或总是返回nil,... ,但是你需要检查对象的类型,.. idk

我认为STI是目前最好的解决方案