views:

1323

answers:

3

I have two models: Person and Relation. The second one stores information about relations between two people. It has parent_id and child_id fields and doesn`t have id field. I connected it with has_many :through and it works.

But:

  1. Relation.find(:all) returns empty array even if there are some relations in the table (becouse there is no id field).
  2. I don`t know how to delete relation.

My models looks like this:

class Person < ActiveRecord::Base
  has_many :child_relations, 
           :class_name => "Relation", 
           :foreign_key => "parent_id"
  has_many :parent_relations, 
           :class_name => "Relation", 
           :foreign_key => "child_id"

  has_many :children, :through => :child_relations
  has_many :parents, :through => :parent_relations
end

class Relation < ActiveRecord::Base
  belongs_to :parent, :class_name => "Person"
  belongs_to :child, :class_name => "Person"
end

Any suggestions?

UPDATE: I've used has_many :through becouse I also store information about a type of the relation in the table. Currently I gave up and I added id field to my table (Rails convention...). But my question remains open.

+3  A: 

has_many :through depends on an id in the join table. It makes the join table a whole model. Since every operation with records happens with an id, you wont be able to directly interface with a table without it. When you delete a record rails generates sql to delete the record by its id. If you have a join table that acts as a full model, it must have an id

Or you can use has_and_belongs_to_many which works more like you expect. The remove a relationship you remove the object via its assocations and not directly with the relationship model.

Your best bet is to add an ID to the join table. That way in the future if the relationship model becomes more complex you can track it as its own entity.

Squeegy
A: 

This should give you a step in the right direction. I am not at a rails prompt to test it, but it should be pretty quick to set up a model and try it. Hope it helps!

class Relation < ActiveRecord::Base
  belongs_to :parent, :class_name => "Person", :foreign_key => :parent_id
  belongs_to :child, :class_name => "Person", :foreign_key => :child_id
end

class Person < ActiveRecord::Base
  has_many :relations
  has_many :children, :through => :relations
  has_many :parents, :through => :relations
end
It doesn't work. You should set foreign keys in Person model, not in Relation. In Relation model Rails will guess names of foreign keys, becouse it will add _id to associations names (parent and child). So probably models specifications should stay as I proposed in my question. But anyway thanks!
klew
A: 

I've successfully used the has_and_belongs_to_many in this situation. The join table only has foreign keys, no id key. One important thing is that you don't have a model for the Relations table, just the two has_and_belongs_to_many references in the Person class

Here is a good thorough treatment on Has and belongs to many

Tilendor