与同一模型的多个关联

我有两个类,我想指定如下:

class Club  "Person", :foreign_key => "president_id" belongs_to :vice_president, :class_name => "Person", :foreign_key => "vice_president_id" end class Person  ['president_id = ? OR vice_president_id = ?', '#{self.id}', '#{self.id}'] end 

这不起作用,并在尝试从人物对象获得俱乐部关联时给出错误。 错误是因为我在查看SQL时在俱乐部表中查找person_id。 我可以通过声明多个has_one关联来解决它,但感觉这是不正确的做法。

一个人只能是一个俱乐部的总裁或副总裁。

任何能够就此问题提供一些建议的人,我都会非常感激。

据我所知,你的has_one条件永远不会在Rails中工作。

在两个表上,每个“链接”需要一个显式的has_onebelongs_to或has_many。 因此,如果您有两个“链接”,则需要两个has_one和两个belongs_to 。 这就是它的工作原理。

其次,我认为你应该重新考虑你的模型。 你这样做的方式,一个人不能同时成为俱乐部和员工的总裁。 或者是两个俱乐部的主席。 即使你现在没有这些,它们也可以在未来出现 – 现在更容易保持灵活性。

一种灵活的方法是使用has_many :through和一个指定角色的中间表。 换一种说法:

 # The memberships table has a person_id, club_id and role_id, all integers class Membership < ActiveRecord::Base belongs_to :club belongs_to :person validates_presence_of :role_id validates_numericality_of :role_id end class Club < ActiveRecord::Base has_many :memberships, :dependent => :delete_all has_many :people, :through => :memberships end class Person < ActiveRecord::Base has_many :memberships, :dependent => :delete_all has_many :clubs, :through => :memberships end 

现在,假设role_id = 0表示employee,role_id = 1表示总统,role_id = 2表示vice_president,您可以像这样使用它:

 tyler = Person.find(1) # person_id is 1 other = Person.find(2) # person_id is 2 c = Club.find(1) # club_id is 1 tyler.clubs # returns all the clubs this person is "member" of c.people # returns all the "members" of this club, no matter their role #make tyler the president of c tyler.memberships.create(:club_id => 1, :role_id => 1) #make other the vicepresident of c #but using c.memberships instead of other.memberships (works both ways) c.memberships.create(:person_id => 2, :role_id => 1) #find the (first) president of c c.memberships.find_by_role_id(1).person #find the (first) vicepresident of c c.memberships.find_by_role_id(2).person #find all the employees of c c.memberships.find_all_by_role_id(0).collect { |m| m.person } #find all the clubs of which tyler is president tyler.memberships.find_all_by_role_id(1).collect { |m| m.club } 

补充说明:

  • 您可以使用角色表和模型来补充这一点。 角色只有一个名字,角色会有have_many关系,而会员资格则belong_to角色。 或者,您可以在成员资格中定义获取角色名称的方法(如果为0,则返回“employee”,如果为1,则为“president”,等等
  • 您可以在成员身上添加validation,这样就可以让不超过1人成为某个俱乐部的主席,或者同一个俱乐部的同一个员工两次。 稍后,如果你开始得到一个人需要在两个地方的“例外情况”,你只需要调整你的validation。

我认为你的联想是错误的。 你的方式很难指派总统或副总统。

我会这样做:

 class Club < ActiveRecord::Base has_one :president, :class_name => "Person", :foreign_key => 'president_club_id' has_one :vice_president, :class_name => "Person", :foreign_key => 'vice_president_club_id' end class Person < ActiveRecord::Base belongs_to :club end 

现在您可以分配如下角色:

 club.president = Person.create(:name => 'Tom') club.vice_president = Person.create(:name => 'Andrew') 

我建议你介绍一个叫做角色的新模型。 然后有以下内容:

 class Club has_many :roles def president end def vice_president end end class Person belongs_to :role end class Role has_one :person belongs_to :club end 

这是多态关联的经典用例。 这是链接: http : //api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

就像是..

 class Club < ActiveRecord::Base belongs_to :person, :polymorphic => true class Person < ActiveRecord::Base has_one :club, :as => :position