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