Topic: Self-referential join through a model -- help

Hello,
I have a model of People and a self-referential join through an intermediate model of Relatives.  Here are the details:

people table:
  t.column :first,  :string, :null => false
  t.column :last,   :string, :null => false

relatives table:
  t.column :source_id, :integer, :null => false
  t.column :sink_id, :integer, :null => false
  t.column :relationship, :string, :null => false

relative.rb:
  belongs_to :parent, :foreign_key => "source_id", :class_name => "Person"
  belongs_to :child,   :foreign_key => "sink_id",   :class_name => "Person"

person.rb:
  has_many  :relatives_as_children,
            :foreign_key => "source_id",
            :class_name => 'Relative',
            :conditions => "relationship = 'Child'"
 
  has_many  :relatives_as_parents,
            :foreign_key => "sink_id",
            :class_name => 'Relative',
            :conditions => "relationship = 'Child'"
           
  has_many  :parents,
            :through => :relatives_as_parents
           
  has_many  :children,
            :through => :relatives_as_children


After we create two people, for example:
bill = Person.create(:first => "Bill", :last => "Clinton")
chelsea = Person.create(:first => "Chelsea", :last => "Clinton")

The following works fine:
Relative.create(:source_id => bill.id, :sink_id => chelsea.id, :relationship => "Child")

However, and I know this is expecting a tremendous amount of Rails magic, but is there any world in which it would be possible instead to simply write:
bill.children << chelsea

??

When I do this, I get an error "undefined method 'person_id=' for #<Relative:0x289dccc>"

Perhaps that's just asking too much, or perhaps my models need to be tweaked a bit.  Advice?

Re: Self-referential join through a model -- help

The << method for has_many : through association was just recently added to edge rails. Apparently it is very simplistic and doesn't use the specified foreign key in the join model.

This may (and really should) be fixed in the future, but even then I do not think this will solve your problem. I don't see how Rails could be smart enough to read the conditions in the relatives_as_children association and set the model attributes accordingly. These conditions could contain anything including regular expressions, SQL functions, and greater than/less than comparisons. It wouldn't know what value to set in order to pass the conditions.

However, you can of course make your own children<< method with the code you gave above. This moves some code from the controller into the model which is usually a good thing.

Railscasts - Free Ruby on Rails Screencasts