Tech Tidbits - Ruby, Ruby On Rails, Merb, .Net, Javascript, jQuery, Ajax, CSS...and other random bits and pieces.

Monday, July 21, 2008

Self Referential Associations with has_many :through


db/migrate/001_create_teletubbies.rb

class CreateTeletubbies < ActiveRecord::Migration
def self.up
create_table :teletubbies do |t|
t.string :name
t.timestamps
end
Teletubby.create(:name => 'Tinky Winky')
Teletubby.create(:name => 'Dipsy')
Teletubby.create(:name => 'Laa Laa')
Teletubby.create(:name => 'Po')
end

def self.down
drop_table :teletubbies
end
end

db/migrate/002_create_friendships.rb

class CreateFriendships < ActiveRecord::Migration
def self.up
create_table :friendships do |t|
t.integer :teletubby_id
t.integer :friend_id
t.timestamps
end
# Tinky Winky loves all the other Teletubbies very much
Friendship.create(:teletubby_id => 1, :friend_id => 2)
Friendship.create(:teletubby_id => 1, :friend_id => 3)
Friendship.create(:teletubby_id => 1, :friend_id => 4)
# Dipsy loves all the other Teletubbies very much
Friendship.create(:teletubby_id => 2, :friend_id => 1)
Friendship.create(:teletubby_id => 2, :friend_id => 3)
Friendship.create(:teletubby_id => 2, :friend_id => 4)
# Laa Laa loves Po very much
Friendship.create(:teletubby_id => 3, :friend_id => 4)
# Po loves Laa Laa very much
Friendship.create(:teletubby_id => 4, :friend_id => 3)
# Big Hug
end

def self.down
drop_table :friendships
end
end

app/models/teletubby.rb

class Teletubby < ActiveRecord::Base
# a teletubby 'has_many' friendships (teletubbies love each other very much)
has_many :friendships

# a teletubby 'has_many' friends ':through' friendships relationship
has_many :friends, :through => :friendships
end

app/models/friendship.rb

class Friendship < ActiveRecord::Base
# ActiveRecord already knows what a teletubby is (reflection)
belongs_to :teletubby

# No actual friendship model, so add :class_name and :foreign_key
belongs_to :friend, :class_name => "Teletubby", :foreign_key => "friend_id"
end


The database should look a little something like this:

mysql> select * from teletubbies;
+----+-------------+---------------------+---------------------+
| id | name | created_at | updated_at |
+----+-------------+---------------------+---------------------+
| 1 | Tinky Winky | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 2 | Dipsy | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 3 | Laa Laa | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 4 | Po | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
+----+-------------+---------------------+---------------------+
4 rows in set (0.00 sec)

mysql> select * from friendships;
+----+--------------+-----------+---------------------+---------------------+
| id | teletubby_id | friend_id | created_at | updated_at |
+----+--------------+-----------+---------------------+---------------------+
| 1 | 1 | 2 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 2 | 1 | 3 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 3 | 1 | 4 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 4 | 2 | 1 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 5 | 2 | 3 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 6 | 2 | 4 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 7 | 3 | 4 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
| 8 | 4 | 3 | 2008-07-21 15:41:42 | 2008-07-21 15:41:42 |
+----+--------------+-----------+---------------------+---------------------+
8 rows in set (0.00 sec)


Use script/console to check the relationships:

dsparling-imbps-computer:~/Sites/teletubbies dsparlingimbp$ script/console
Loading development environment (Rails 2.0.2)
>> t1 = Teletubby.find(1)
=> #<Teletubby id: 1, name: "Tinky Winky", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42">
>> t1.friends.each { |f| puts "#{t1.name} loves #{f.name} very much." }; false
Tinky Winky loves Dipsy very much.
Tinky Winky loves Laa Laa very much.
Tinky Winky loves Po very much.
=> false
>> t2 = Teletubby.find(2)
=> #<Teletubby id: 2, name: "Dipsy", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42">
>> t2.friends.each { |f| puts "#{t2.name} loves #{f.name} very much." }; false
Dipsy loves Tinky Winky very much.
Dipsy loves Laa Laa very much.
Dipsy loves Po very much.
=> false
>> t3 = Teletubby.find(3)
=> #<Teletubby id: 3, name: "Laa Laa", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42">
>> t3.friends.each { |f| puts "#{t3.name} loves #{f.name} very much." }; false
Laa Laa loves Po very much.
=> false
>> t4 = Teletubby.find(4)
=> #<Teletubby id: 4, name: "Po", created_at: "2008-07-21 15:41:42", updated_at: "2008-07-21 15:41:42">
>> t4.friends.each { |f| puts "#{t4.name} loves #{f.name} very much." }; false
Po loves Laa Laa very much.
=> false

No comments:

About Me

My photo
Developer (Ruby on Rails, iOS), musician/composer, Buddhist, HSP, Vegan, Aspie.

Labels