多个关联到同一个模型 [英] Multiple Associations to Same Model
问题描述
我有两个,我想指定类别如下:
I have two classes that I would like to specify as follows:
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
试图从人的对象,俱乐部的关联时,这并不工作,给我一个错误。这个错误是因为正在寻找在俱乐部表为person_id当我看着SQL。我可以绕过它宣布多个HAS_ONE协会,但觉得这是做这件事的方式不当。
This doesn't work and gives me an error when trying to get the club association from the person object. The error is because is looking for person_id in the club table when I looked at the SQL. I can get around it by declaring multiple has_one associations, but feel like this is the improper way of doing it.
一个人只能有一个俱乐部的president或副president。
A person can only be the President or Vice President of one club.
任何人都可以提供咨询的一点点关于这个问题,我会非常AP preciative。
Anyone able to offer a little bit of advice on this issue, I would be very appreciative.
推荐答案
您 HAS_ONE
情况绝不会在工作Rails的,据我所知。
Your has_one
condition will never work in Rails, as far as I know.
您需要一个明确的 HAS_ONE
或 belongs_to的
或按链接,这两个表的has_many。所以,如果你有两个三通,则需要两个 HAS_ONE
和两个 belongs_to的
。这是如何工作的。
You need one explicit has_one
or belongs_to
or has_many per "link", on both tables. So if you have two "links", you need two has_one
and two belongs_to
. That is how it works.
其次,我认为你应该重新考虑你的模型。你正在做的方式,一个人不可能是president俱乐部和雇员,在同一时间。或者是两家具乐部的president。即使你没有这些,现在,他们可以进来以后 - 它更容易保持灵活性,现在
Secondly, I think you should reconsider your models. The way you are doing it, one person can not be the president of a club and an employee, at the same time. Or be the president of two clubs. Even if you don't have these right now, they can come in the future - it is easier to stay flexible right now.
这样做的一个灵活的方法是使用的has_many:通过
与中间表,指定的作用。换句话说:
A flexible way of doing this is using a has_many :through
with an intermediate table that specifies the role. In other words:
# 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表示president,并ROLE_ID = 2表示vice_ president,你可以使用这样的:
Now, assuming that role_id=0 means employee, role_id=1 means president, and role_id=2 means vice_president, you can use it like this:
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 }
其他注意事项:
Additional notes:
- 您可以用一个角色表和型号补充这一点。角色本来只是AA名,角色会
have_many
的关系,会员将belong_to
的作用。或者,你可以定义为获取角色名称(如果为0,则返回雇员的成员方法,如果为1,president等 - 您可以在memberhips所以不超过1人可在给定的俱乐部,或者在同一家具乐部同一名员工的president两次加验证。后来,如果你开始得到特殊情况下,其中一人需要在两个地方,你就只能去适应你的验证。
- You could complement this with a roles table and model. Roles would have just a a name, roles would
have_many
relationships and memberships wouldbelong_to
role. Or, you could define methods in memberships for getting the role name (if 0, it returns "employee", if 1, "president", etc - You can add validations on memberhips so no more than 1 person can be made president of a given club, or the same employee on the same club twice. Later on, if you start getting "exceptional cases" in which a person needs to be in two places, you will just have to adapt your validations.
这篇关于多个关联到同一个模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!