Self-referencing relationships

I have a question on how to approach a simple self-referencing data
model in Rails:

I have a table called “relationships”:

create_table :relationships do |t|
t.integer :user_id
t.integer :is_relationship_with
t.string :relationship

t.timestamps
end

And a table called “user”

create_table “users”, :force => true do |t|
t.column :login, :string
t.column :email, :string
#… and so on…
end

A relationship could be one of the following: friend_of, student_of,
parent_of. Any user should be able to have one or more of these, but
of course should be defined only once as one of these three options.

My question is, how would I do this in the model? I am assuming it
would go into my model/relationships.rb file using something like a
has_and_belongs_to_many instruction, but not sure how that should look
given the recursive nature of this data model. Any strategic advice
would be most appreciated!

Cheers,
Joe

On Apr 25, 11:25 am, Joe L. [email protected] wrote:

A relationship could be one of the following: friend_of, student_of,
parent_of. Any user should be able to have one or more of these, but
of course should be defined only once as one of these three options.

Just a correction: Any user could have any number of such
relationships. (Started this question out using my Roles model where
that would have made more sense…)

And to further clarify my Relationships data:

t.integer :user_id # is the obvious foreign key back to the user
table.
t.integer :is_relationship # is the foreign key back to the user table
for whom this relationship is being applied. (name changed slightly
from earlier post)
t.string :relationship # can be friend_of, student_of, parent_of.
replaces the relationship part of the above field.

I can see in my relationships.rb model that this might be a start:

class Relationship < ActiveRecord::Base
has_many :users, :through => :relationships
end

But I’m confused about what to do about the :is_relationship part, and
in turn what I would need to put in the user model -
has_many :relationships ?

I was just looking for a solution to this myself! I didn’t find one so
I had a play, and came up with the following example. It all seemed to
work quite nicely so I thought I’d post it

Overview

I’ve used a twitter metaphor with users, followers, and leaders:

I have 2 classes, one called “User”, and one called “UserFollower”
which is basically a self referential linking table.

In the user_followers table there is two foreign keys - user_id and
follower_id

Code

class User < ActiveRecord::Base
has_many :user_followers
has_many :followers, :through => :user_followers

has_many :user_leaders, :class_name => “UserFollower”, :foreign_key
=> “follower_id”
has_many :leaders, :through => :user_leaders, :source => :user
end

class UserFollower < ActiveRecord::Base
belongs_to :user
belongs_to :follower, :class_name => “User”
end

Console Session

user = User.create( :name => “Jono” )
=> #<User id: 1, name: “Jono”, created_at: “2008-04-29 15:33:02”,
updated_at: “2008-04-29 15:33:02”>

User.create( :name => “David” )
=> #<User id: 2, name: “David”, created_at: “2008-04-29 15:33:13”,
updated_at: “2008-04-29 15:33:13”>

user.followers
=> []

user.user_followers.create( :follower => User.find(2) )
=> #<UserFollower id: 1, user_id: 1, follower_id: 2, created_at:
“2008-04-29 15:34:25”, updated_at: “2008-04-29 15:34:25”>

user.followers
=> [#<User id: 2, name: “David”, created_at: “2008-04-29 15:33:13”,
updated_at: “2008-04-29 15:33:13”>]

user = User.find(2)
=> #<User id: 2, name: “David”, created_at: “2008-04-29 15:33:13”,
updated_at: “2008-04-29 15:33:13”>

user.followers
=> []

user.leaders
=> [#<User id: 1, name: “Jono”, created_at: “2008-04-29 15:33:02”,
updated_at: “2008-04-29 15:33:02”>]

I’ve written a tutorial on this now because it’s such a frequently asked
question: