Randy Schmidt on 27 Feb 2006 19:54:43 -0000


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[PhillyOnRails] self-referential many-to-many using a join model


Hello!

I sent this email to the Rails Mailing list but haven't received a
response. It's bugging me because I want to take advantage of join
models but I can't get it to work quite right since what I am doing is
self-referential. I know the email is long, but any help would be
greatly appreciated! For some reason, I think I am just missing one
key bit of code...

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
_______________________________________________
talk mailing list
talk@phillyonrails.org
http://lists.phillyonrails.org/mailman/listinfo/talk