2013-06-04 26 views
0

假设我们有教练,客户和用户。在Rails中建立这种关系最常用的方式是什么?

以非继承的方式对此进行建模的理想方式是什么?我想避免STI。

现在,我有这样的事情:

user.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的正确惯用方式分开?

“网站用户”可以存在而不是coachclient

如果建模只需要一个关系,那么我可以看到它是一个HABTM,但是如果个人关系需要额外的逻辑呢?例如客户或教练的额外逻辑?你会混入一个在用户模型中定义逻辑的类吗?或者你会为这种关系创建单独的AR模型,如果是这样,如何?

+1

为什么你要避免使用STI?这是一个很好的例子。 – Substantial

+0

从我收集的信息来看,STI通常是一个不好的解决方案,但如果这是一个完美的案例...... –

+0

如果做得好,尽管很容易被滥用,STI仍然运作良好。请注意,'用户'将成为一个抽象类,你只能通过它的子类与它进行交互。例如,必须实例化一个'Coach'或''Client',而不是'User'。尽管如此,许多人违反了这条规则,将肮脏的黑客扼杀Rails的内置支持,沮丧并撰写博文指责STI是一种“糟糕的解决方案”。如果你愿意放弃对'User'的控制,我会为你写一个答案。 – Substantial

回答

1

如果一个client/coach只是一种关系,它可能就是这样,而不是一个单独的模型。所以你可以在Users之间做一个has_and_belongs_to_many的关系。创建迁移:

def up 
    create_table :coaches_clients do |t| 
     t.integer :coach_id 
     t.integer :client_id 
    end 
    end 

和你的模型:

has_and_belongs_to_many :clients, 
     :foreign_key => 'client_id', 
     :association_foreign_key => 'coach_id', 
     :class_name => 'User', 
     :join_table => 'coaches_clients' 

has_and_belongs_to_many :coaches, 
     :foreign_key => 'coach_id', 
     :association_foreign_key => 'client_id', 
     :class_name => 'User', 
     :join_table => 'coaches_clients' 
+0

好的,谢谢。说得通。如果您要预防的是客户或教练可能需要额外的逻辑,那么您将如何对此进行建模? –

+0

这确实取决于你的需求,但是我发现有一个'user'模型,has_one' coach模型和'has_one'客户端模型是很方便的。这样,用户的详细信息和逻辑就可以单独与用户分享,用户可以既是教练又是客户。这样教练的逻辑就可以用“教练”模式。不知道它是多么地道,我想你会调用'user.coach.clients'等。 – flyingjamus

相关问题