views:

2226

answers:

4

Relatively new to rails and trying to model a very simple family "tree" with a single Person model that has a name, gender, father_id and mother_id (2 parents). Below is basically what I want to do, but obviously I can't repeat the :children in a has_many (the first gets overwritten).

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

Is there a simple way to use has_many with 2 foreign keys, or maybe change the foreign key based on the object's gender? Or is there another/better way altogether?

Thanks!

+3  A: 

I believe you can achieve the relationships you want using :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

I'll confirm and edit this answer after work ; )

Gordon Wilson
+4  A: 

Found a simple answer on IRC that seems to work (thanks to 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
Kenzie
A: 

But this won't works with:

father.children.find(params[:id])!

Arrays don't have a find-method....

A: 

Used named_scopes over the Person model do this:

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
Zando