50 votes

Modèle Rails has_many avec plusieurs foreign_keys

Relativement nouveau sur les rails et essayer de modéliser une famille très simple de "l'arbre" avec un seul modèle Personne qui a un nom, le sexe, father_id et mother_id (2 parents). Ci-dessous est en gros ce que je veux faire, mais évidemment je ne peux pas répéter l' :les enfants dans un has_many (la première est écrasée).

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

Est-il une façon simple d'utiliser has_many avec 2 clés étrangères, ou peut-être modifier la clé étrangère fondée sur l'objet de l'égalité entre les sexes? Ou est-il un meilleur moyen tout à fait?

Merci!

44voto

Kenzie Points 604

J'ai trouvé une réponse simple sur IRC qui semble fonctionner (grâce à 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
 

9voto

Zando Points 1472

Named_scopes utilisés sur le modèle de personne font ceci:

 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
 

6voto

Gordon Wilson Points 14721

Je crois que vous pouvez réaliser les relations que vous souhaitez utiliser: 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
 

Je vais confirmer et éditer cette réponse après le travail; )

4voto

Brunno Dos Santos Points 949

Je préfère utiliser des étendues pour ce problème. Comme ça:

 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
 

Cette astuce facilite l'obtention d'enfants sans instances d'utilisation:

 Person.children_for father_id, mother_id
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X