我有两个类,我想指定如下:
class Club < ActiveRecord::Base
belongs_to :president, :class_name => "Person", :foreign_key => "president_id"
belongs_to :vice_president,
:class_name => "Person",
: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关联来解决它,但感觉这是不正确的做法。
一个人只能是一个俱乐部的总裁或副总裁。
任何能够就此问题提供一些建议的人,我都会非常感激。
答案 0 :(得分:8)
据我所知,你的has_one
条件在Rails中永远不会有效。
两个表都需要一个明确的has_one
或belongs_to
或has_many per“link”。因此,如果您有两个“链接”,则需要两个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 }
附加说明:
have_many
关系和成员资格belong_to
角色。或者,您可以在成员资格中定义获取角色名称的方法(如果为0,则返回“employee”,如果为1,则为“president”等答案 1 :(得分:0)
我认为你的联想是错误的。你的方式很难指派总统或副总统。
我会这样做:
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')
答案 2 :(得分:0)
我建议你介绍一个叫做角色的新模型。然后有以下内容:
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
答案 3 :(得分:0)
这是多态关联的经典用例。 链接在这里: 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