STI and foreign_key problem

Hi,

I am trying to use STI since my classes only vary by one column in the
database.
Here is the structure (names have been changed to protect the innocent):

  Case
/       \

Registered Initial
\ /
Children

A registered case has additional information than an initial case (I
realize I could just set a flag to separate them, but there is a good
reason to separate them), but both need to be related to the children
table. Here is the model code:

class Case < ActiveRecord::Base
end

class Registered < Case
has_many :children, :foreign_key => “case_id”
end

class Initial < Case
has_many :children, :foreign_key => “case_id”
end

class Child < ActiveRecord::Base
belongs_to :initial
belongs_to :registered
end

When I attempt to access the children attribute via an Initial object I
get an unknown column exception and the dump shows the sql is trying to
select “initial_id” from the children table. This despite the fact I
specified the foreign key of ‘case_id’ in the Initial model.

This has been driving me crazy this evening. All searches for help have
come up empty. Anyone help would be greatly appreciated.

Thanks!

Peer

Hi Peer,

With your structure you can add the line
has_many :children, :foreign_key => “case_id”
to the case definition.

The reason that the sql is looking for the initial_id is because the
class
Child belongs to it.

There are 3 options,

  1. Include an initial_id and a registered_id to your children table
    If there is a requirement that it belongs to an inital or registered
    case
    only include that in the validation of the child object.

  2. Include a case_id in the Child table and change the Child class
    definition to:
    class Child < ActiveRecord::Base
    belongs_to :initial, :foreign_key => ‘case_id’
    belongs_to :registered, :foreign_key => ‘case_id’
    end

I don’t know the wisdom of doing this one. Having never tried it it may
milage may be non-existant.

  1. Make Child polymorphic. Then you can associate children with
    anything.

I would tend to go for option 3. It’s cleaner and allows for the
future.

Sorri to repost so soon,

Looking at your associations, you already have the case_id in the child
table.

With STI initial and registered ARE cases. So you can just use the
case_id. When you query it you can decide.

child.case.type will tell you what class it is.

Peer A. wrote:

Daniel ----- wrote:

Sorri to repost so soon,

Looking at your associations, you already have the case_id in the child
table.

With STI initial and registered ARE cases. So you can just use the
case_id. When you query it you can decide.

child.case.type will tell you what class it is.

This is how I thought it was designed to work and how I thought I had
the classes configured to work just like you described here. Am I
missing something?

Peer

I figured out what I was doing wrong and I don’t think I want to mention
it in public. But since some nuby (like me) might do the same thing in
the future I guess it is only right that I do.

When I initially made the system I made separate models for Initial and
Registered then I tried to switch it to STI. I know now that I setup up
the STI correclty. However, I redeclared my classes, Initial and
Registered, in the new case.rb file and did not delete the old model
files. Parts of it were working so I thought everything was alright,
but I was still using the old models that weren’t configured properly
and hence the errors. Once I removed the old files and added the link
to the case model in application.rb everything worked just fine.
Whoops!

Thanks for listening (and helping Daniel!)

Peer

Daniel ----- wrote:

Sorri to repost so soon,

Looking at your associations, you already have the case_id in the child
table.

With STI initial and registered ARE cases. So you can just use the
case_id. When you query it you can decide.

child.case.type will tell you what class it is.

This is how I thought it was designed to work and how I thought I had
the classes configured to work just like you described here. Am I
missing something?

Peer