问题
I need to access institution in two ways. My models are given below:
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
The i setup the models like this is that person can study in different institutions, so for this i setup
has_many :institutions, :through => :institution_people
for person model
But at the same time person can have institution choices, so i setup
has_many :institutions, :through => :institution_choices
for person model.
How should i setup model and association between person and institutions so that i can find institutions from person in both ways.
Right now
Person.first.institutions
finds from institution_people table, as
has_many :institutions, :through => :institution_people
is at beginning i guess.
Some other techniques are welcomed so that i can get institutions in both ways.
回答1:
In your Person
model, try this :
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
回答2:
Basically, you need some kind of interface here. What i would do:
in institutions model:
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]
( it joins the query(scope) from Person.rb below )
in 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])
(this should retrieve all institutions ids from both tables)
ugly as hell, but still might work. You could use is then like: Institution.institutions_of(current_user)
回答3:
If you don't need to keep the result as an ActiveRelation
class Person < ActiveRecord::Base
has_many :institution_people
has_many :institution_choices
def institutions
institution_people + institution_choices
end
end
If you DO need the keep it (in order to call person.institutions.order('name'), by example), then it's more complicated:
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
来源:https://stackoverflow.com/questions/5701175/access-has-many-relation-in-two-different-ways-activerecord-rails