Rails Model has_many con múltiples foreign_keys

Relativamente nuevo en rails e intentando modelar un “árbol” familiar muy simple con un modelo de persona única que tiene un nombre, género, id_pad y id_madre (2 padres). Debajo está básicamente lo que quiero hacer, pero obviamente no puedo repetir lo siguiente: niños en un has_many (el primero se sobrescribe).

class Person  'Person' belongs_to :mother, :class_name => 'Person' has_many :children, :class_name => 'Person', :foreign_key => 'mother_id' has_many :children, :class_name => 'Person', :foreign_key => 'father_id' end 

¿Existe una forma simple de usar has_many con 2 claves externas, o tal vez cambiar la clave externa en función del género del objeto? ¿O hay otra / mejor manera en conjunto?

¡Gracias!

Encontré una respuesta simple en IRC que parece funcionar (gracias a Radar):

 class Person < ActiveRecord::Base belongs_to :father, :class_name => 'Person' belongs_to :mother, :class_name => 'Person' has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id' has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id' def children children_of_mother + children_of_father end end 

Para mejorar la respuesta de Kenzie , puede lograr una relación de ActiveRecord definiendo Person#children como:

 def children children_of_mother.merge(children_of_father) end 

vea esta respuesta para más detalles

Creo que puedes lograr las relaciones que deseas usando: has_one.

 class Person < ActiveRecord::Base has_one :father, :class_name => 'Person', :foreign_key => 'father_id' has_one :mother, :class_name => 'Person', :foreign_key => 'mother_id' has_many :children, :class_name => 'Person' end 

Confirmaré y editaré esta respuesta después del trabajo; )

Utiliza named_scopes sobre el modelo Person para hacer esto:

 class Person < ActiveRecord::Base def children Person.with_parent(id) end named_scope :with_parent, lambda{ |pid| { :conditions=>["father_id = ? or mother_id=?", pid, pid]} } end 

Prefiero usar ámbitos para este problema. Me gusta esto:

 class Person < ActiveRecord::Base belongs_to :father, :class_name => 'Person' belongs_to :mother, :class_name => 'Person' has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id' has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id' scope :children_for, lambda {|father_id, mother_id| where('father_id = ? AND mother_id = ?', father_id, mother_id) } end 

Este truco hace que sea fácil obtener hijos sin instancias de uso:

 Person.children_for father_id, mother_id 

No es una solución a la pregunta general tal como se establece (“has_many with multiple foreign keys”), pero dado que una persona puede ser madre o padre, pero no ambas cosas, agregaría una columna de gender e iría con

  has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id' has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id' def children gender == "male" ? children_of_father : children_of_mother end 

Estaba buscando la misma característica, si no desea devolver una matriz sino ActiveRecord::AssociationRelation , puede usar < < lugar de + . ( Consulte la documentación de ActiveRecord )

 class Person < ActiveRecord::Base belongs_to :father, :class_name => 'Person' belongs_to :mother, :class_name => 'Person' has_many :children_of_father, :class_name => 'Person', :foreign_key => 'father_id' has_many :children_of_mother, :class_name => 'Person', :foreign_key => 'mother_id' def children children_of_mother < < children_of_father end end 

Mi respuesta a Asociaciones y (múltiples) claves foráneas en Rails (3.2): ¡cómo describirlas en el modelo y escribir migraciones es para ti!

En cuanto a su código, aquí están mis modificaciones

 class Person < ActiveRecord::Base belongs_to :father, :class_name => 'Person' belongs_to :mother, :class_name => 'Person' has_many :children, ->(person) { unscope(where: :person_id).where("father_id = ? OR mother_id = ?", person.id, person.id) }, class_name: 'Person' end 

¿Alguna pregunta?