references rails inverse_of has_and_belongs_to_many foreign belong association ruby-on-rails ruby model has-many

ruby on rails - inverse_of - Rails Model has_many con mĂșltiples foreign_keys



rails references (8)

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; )

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 < ActiveRecord::Base belongs_to :father, :class_name => ''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


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 rieles (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?


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


Para mejorar la respuesta de , 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


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


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