【发布时间】:2013-06-04 01:09:07
【问题描述】:
假设我们有教练、客户和用户。
以非继承的方式对此进行建模的理想方法是什么?我想避免 STI。
现在我有这样的东西:
用户.rb
has_many :coaches, :foreign_key => :client_id
has_many :coach_users, :through => :coaches, :source => :user
has_many :clients, :class_name => "Coach"
has_many :client_users, :through => :clients, :source => :client
def is_a_coach_of?(client)
self.client_users.include?(client)
end
def is_a_client_of?(coach)
self.coach_users.include?(coach)
end
coach.rb
belongs_to :user
belongs_to :client, :class_name => "User"
但是,要处理一个被认为是“教练”的用户对象并且必须键入 user.coach_users 来获取由该特定用户指导的用户集合,这感觉真的很笨重。
感觉非常不习惯,老实说,它只是令人困惑,我讨厌它。我想要更优雅的东西。
我想删除连接模型,只在 user.rb 模型上添加两个 has_many,但它仍然感觉很笨拙,尤其是违反对象角色的恶心感觉。这些是不同的角色,但也非常相似,因为它们都是用户。您如何使用 Rails 和 Ruby 以优雅的方式,以正确的惯用方式分离这些常见逻辑?
“网站用户”可以在不是coach 或client 的情况下存在。
如果建模只需要一个关系,那么我可以看到它是一个 HABTM,但如果单个关系需要额外的逻辑怎么办?例如,客户或教练的额外逻辑?你会在 User 模型中混入一个定义逻辑的类吗?或者您会为这种关系创建单独的 AR 模型吗?如果是,如何创建?
【问题讨论】:
-
为什么要避免使用 STI?这是一个很好的例子。
-
据我所知,STI 通常不是解决问题的好方法,但如果这是完美的情况......
-
STI 如果操作得当,效果会很好,尽管它很容易被误用。请注意,
User将成为一个抽象类,您只能通过它的子类与它进行交互。例如,必须实例化Coach或Client,而不是User。尽管如此,还是有很多人打破了这个规则,加入了肮脏的黑客来减少 Rails 的内置支持,感到沮丧并写博客文章指责 STI 是“糟糕的解决方案”。如果你愿意放弃对User的控制权,我会为你写一个答案。 -
不过就是这样,也会有用户。用户可以存在而不是
client或coach。客户或教练只是用户之间的一种关系,可能有也可能没有这种关系。
标签: ruby-on-rails activerecord