2010-01-24 8 views
7

tengo un modelo, Couple, que tiene dos columnas, first_person_id y second_person_id y otro modelo, Person, cuya clave principal es person_id y tiene la columna nameActiveRecord has_many donde dos columnas de la tabla A son las claves principales en la tabla B

aquí está el uso que quiero:

#including 'Person' model for eager loading, this is crucial for me 
c = Couple.find(:all, :include => :persons)[0] 
puts "#{c.first_person.name} and #{c.second_person.name}" 

Entonces, ¿cómo puedo hacer esto?

+0

Si está utilizando rieles, ¿por qué la clave principal en el modelo de persona ser "person_id "y no solo" id "? – tfwright

+0

Cambié los nombres de mis modelos para esta publicación porque me gustaría mantener los nombres fuera de internet. Debería ser 'id' pero eso no es una solución difícil. Solo usa 'set_primary_key'. – user94154

Respuesta

13

Las relaciones declaradas en Couple debería tener este aspecto:

class Couple 
    named_scope :with_people, { :include => [:first_person, :second_person] } 
    belongs_to :first_person, :class_name => 'Person' 
    belongs_to :second_person, :class_name => 'Person' 
end 

#usage: 
Couple.with_people.first 
# => <Couple ... @first_person: <Person ...>, @second_person: <Person ...>> 

Los que están en Person dependen de si un Person puede ser parte de más de un Couple. Si un Person sólo puede pertenecer a uno Couple y no puede ser el "primero" Person en uno y el Second en otro, es posible que desee:

class Person 
    has_one :couple_as_first_person, :foreign_key => 'first_person_id', :class_name => 'Couple' 
    has_one :couple_as_second_person, :foreign_key => 'second_person_id', :class_name => 'Couple' 

    def couple 
    couple_as_first_person || couple_as_second_person 
    end 
end 

si un Person puede pertenecer a varios Couple s, y no hay no hay manera de saber si ellos son la "primera" o "segundo" en cualquier dada Couple, es posible que desee:

class Person 
    has_many :couples_as_first_person, :foreign_key => 'first_person_id', :class_name => 'Couple' 
    has_many :couples_as_second_person, :foreign_key => 'second_person_id', :class_name => 'Couple' 

    def couples 
    couples_as_first_person + couples_as_second_person 
    end 
end 
+0

Esta es una respuesta bien escrita y bien pensada. Muchas gracias. Voy a probar esto pronto y dejarte saber. – user94154

+0

no lo he probado todavía, pero usted GANÓ :) – user94154

+0

Acabo de hacer algo como esto usando AREL: 'def widgets; Widget.where ( Wiget.arel_table [: asset1_id] .EQ (id) .o ( Widget.arel_table [: asset2_id] .EQ (id) ) ); final' – thekingoftruth

0

no probado, pero de acuerdo con la Rails API documentation, tal vez algo como:

class Couple < ActiveRecord::Base 
    has_one :person, :foreign_key => :first_person_id 
    has_one :person, :foreign_key => :second_person_id 
end 
+0

Esos deberían ser belongs_to, not has_one, ya que las claves foráneas están en este modelo. – tfwright

0

teoría única, no probado:

Cree dos subclases de la persona:

class FirstPerson < Person 
    belongs_to :couple 

class SecondPerson < Person 
    belongs_to :couple 

Pareja has_many clase de cada :

class Couple 
    has_many :first_persons, :foreign_key => :first_person_id 
    has_many :second_persons, :foreign_key => :second_person_id 

luego encontrar:

Couple.all(:include => [:first_persons, :second_persons]) 
+0

no debería un par 'has_one: first_person' y': second_person'? – user94154

Cuestiones relacionadas