Randy Schmidt
2006-Feb-27 17:27 UTC
[Rails] self-referential many-to-many using a join model
Hello! I have been working on making a self-referential habtm relationship that uses a join model because I want to store info about the relationship. I have been using two sections from Chad Fowler''s "Rails Recipes" as a guide, "Self-referential Many-to-Many Relationships" and "Many to Many Relationships Where the Relationship Itself has Data". So far I have had little luck. Here is what I have that works a little, but not really: Migrations: create_table "users" do |t| t.column "name", :string t.column "email", :string end create_table "friends" do |t| t.column "user_id", :integer t.column "acquaintance_id", :integer t.column "approved", :integer end Models: class Friend < ActiveRecord::Base belongs_to :users belongs_to :friends end class User < ActiveRecord::Base has_many :friends has_many :acquaintances, :through => :friends, :class_name => "User" end I can''t figure out those declarations to get it to work like a join model. With that setup, I add a record to the friends table that has the attributes I want (so I can see if I can access the info correctly) - user_id = 1 acquaintance_id = 2 approved = 0>> u1 = User.find(1)=> #<User:0x23754e4 @attributes={"name"=>"Randy", "id"=>"1", "email"=>"x@altorg.com"}>>> u1.acquaintances=> [#<User:0x23722a8 @attributes={"name"=>"Randy", "id"=>"1", "email"=>"x@altorg.com"}>] and uses the following sql: SELECT users.* FROM friends, users WHERE (users.id = friends.user_id AND friends.user_id = 1) which is close to what I want, but I believe it should be the following: SELECT users.* FROM friends, users WHERE (users.id friends.acquaintance_id AND friends.user_id = 1) now I delete that record to try to create that row using ruby>> u1 = User.find(1)=> #<User:0x23754e4 @attributes={"name"=>"Randy", "id"=>"1", "email"=>"x@altorg.com"}>>> u2 = User.find(2)=> #<User:0x2372cbc @attributes={"name"=>"Rebecca", "id"=>"2", "email"=>"something@gmail.com"}>>> friend = Friend.create(:approved => 0)=> #<Friend:0x23700ac @attributes={"id"=>9, "approved"=>0, "acquaintance_id"=>nil, "user_id"=>nil}, @errors=#<ActiveRecord::Errors:0x236e57c @errors={}, @base=#<Friend:0x23700ac ...>>, @new_record=false>>> u1.friends << friend=> [#<Friend:0x23700ac @attributes={"id"=>9, "approved"=>0, "acquaintance_id"=>nil, "user_id"=>1}, @errors=#<ActiveRecord::Errors:0x236e57c @errors={}, @base=#<Friend:0x23700ac ...>>, @new_record=false>]>> u2.friends << friend=> [#<Friend:0x23700ac @attributes={"id"=>9, "approved"=>0, "acquaintance_id"=>nil, "user_id"=>2}, @errors=#<ActiveRecord::Errors:0x236e57c @errors={}, @base=#<Friend:0x23700ac ...>>, @new_record=false>] Here is what I think the problem is. with a normal join model, there are two different types of objects being joined, ie readers and magazines (to steal the example). With what I am doing, both u1 and u2 are User objects, making it so that user_id is always set, but never acquaintance_id. I tried setting association_foreign_key => "acquaintance_id" and foreign_key => "user_id", but that doesn''t work. I have been trying to work this out but have had zero success. At least I think I know what the problem is, but I can''t figure out the solution. One thing I was thinking is maybe making an Acquaintance model that inherits from User so that they are two different object types, but I don''t know if that is possible or if that is a good way to do it. Any help would be greatly appreciated! Thank you! -- Randy Schmidt x@altorg.com 267.334.6833