ruby-on-rails – 同一模型的多个关联

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 同一模型的多个关联前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有两个类,我想指定如下:
class Club < ActiveRecord::Base
  belongs_to :president,:class_name => "Person",:foreign_key => "president_id"
  belongs_to :vice_president,:foreign_key => "vice_president_id"
end

class Person < ActiveRecord::Base
  has_one :club,:conditions => 
  ['president_id = ? OR vice_president_id = ?','#{self.id}','#{self.id}']
end

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

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

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

解决方法

据我所知,你的has_one条件在Rails中永远不会起作用.

在两个表上,每个“链接”需要一个显式的has_one或belongs_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表示员工,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 }

补充说明:

>您可以使用角色表和模型对此进行补充.角色只有一个名字,角色会有很多关系,而会员资格则属于角色.或者,您可以在成员资格中定义获取角色名称方法(如果为0,则返回“employee”,如果为1,“President”等>您可以在成员身上添加验证,因此不能超过1人成为特定俱乐部的主席,或同一俱乐部的同一员工两次.稍后,如果你开始得到一个人需要在两个地方的“例外情况”,你只需要调整你的验证.

猜你在找的Ruby相关文章