我有两个类,我想指定如下:
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人成为特定俱乐部的主席,或同一俱乐部的同一员工两次.稍后,如果你开始得到一个人需要在两个地方的“例外情况”,你只需要调整你的验证.