以两种不同的方式访问has_many关系ActiveRecord Rails

问题描述:

我需要通过两种方式访问​​机构。 我的模型如下:以两种不同的方式访问has_many关系ActiveRecord Rails

class Person < ActiveRecord::Base 
    has_many :institution_people 
    has_many :institution_choices 
    has_many :institutions, :through => :institution_people 
    has_many :institutions, :through => :institution_choices 
    fields........ 
end 

class Institution < ActiveRecord::Base 
    has_many :people, :through => :institution_people 
    has_many :people, :through => :institution_choices 
    has_many :institution_people 
    has_many :institution_choices 
end 

class InstitutionChoice < ActiveRecord::Base 
    belongs_to :person 
    belongs_to :institution 
end 

class InstitutionPerson < ActiveRecord::Base 
    belongs_to :person 
    belongs_to :institution 
end 

的我的设置是这样的模式是,人可以在不同的机构学习,所以为了这个,我设置

has_many :institutions, :through => :institution_people 

的人模型

但在同一时间人可以有机构选择,所以我设置

has_many :institutions, :through => :institution_choices 

为人模型。

我应该如何建立人与机构之间的模型和联系,以便我可以从两种方式找到人的机构。

眼下

Person.first.institutions 

从institution_people表认为,正如

has_many :institutions, :through => :institution_people 

是在开始的时候我猜。

欢迎其他一些技术,以便我可以在两种方式获得机构。

在你Person模型,试试这个:

class Person < ActiveRecord::Base 
    has_many :institution_people 
    has_many :institution_choices 
    has_many :institutions_people, :through => :institution_people, :source => :institutions, :class_name => "Institution" 
    has_many :institutions_choices, :through => :institution_choices, :source => :institutions, :class_name => "Institution" 
end 

http://guides.rubyonrails.org/association_basics.html#has_many-association-reference

+0

这似乎是一个不错的解决方案。我一定会尝试。 – Gagan 2011-04-19 05:19:27

+0

然后投票或接受ಠ_ಠ – 2011-04-20 09:10:04

基本上,你需要某种接口在这里。我会做什么:

在机构模型:

scope :institutions_of, proc { |person| joins(' INNER JOIN (' + Person.institution_ids(person) + ') q 
    ON institutions.id = q.ip_iid OR institutions.id = q.ic_iid').where(['institutions.person_id = ?', person_id] 

(它加入从下面Person.rb查询(范围))

在Person.rb

scope :institution_ids, proc { |person| select('ip.institution_id ip_idd, ic.institution_id ic_idd 
from institution_people ip 
inner join institution_choice ic on ip.person_id = ic.person_id'). 
where(['ip.person_id = ?', person.id]) 

(这应该从两个表中检索所有机构ID)

丑陋地狱,但仍然可能工作。你可以使用然后像:Institution.institutions_of(current_user)

如果您不需要保持结果作为ActiveRelation

class Person < ActiveRecord::Base 
    has_many :institution_people 
    has_many :institution_choices 

    def institutions 
    institution_people + institution_choices 
    end 
end 

如果您确实需要保持它(为了调用person.institutions.order( 'name'),那么它更复杂:

class Person < ActiveRecord::Base 
    has_many :institution_people 
    has_many :institution_choices 

    scope :institutions, :select => 'select * from (select * from institution_people union all select * from institution_choices) as institutions' 
end 
+0

这是在这两种情况下的额外查询。我一直在努力避免这种情况。不知道什么可能会表现出更好的表现:) – 2011-04-18 13:01:57

+0

试试我的答案,这是最好的方式。 – 2011-04-18 18:17:00