Skip to content

Tag Archive for migration

has_many :through Self-referential Example

While using an association table for the first time with Ruby On Rails I had a bit of trouble finding an easy to understand example of has_many :through. I needed to build a self-referencing table where People could have other People as friends through a Friendship. I was getting “stack too deep” errors, “could not find the association” errors, and also crashing Webrick before I figured out the correct setup. Here’s how I did it:

# the people table
create_table :people do |t|
  t.column :name, :string
end

# the friendships association table
create_table :friendships do |t|
  t.column :person_id, :integer
  t.column :friend_id, :integer
  t.column :authorized, :boolean, :default => false
end

class Friendship < ActiveRecord::Base
  # don't have to give class_name or foreign_key b/c ActiveRecord reflection works here
  belongs_to :person

  # make sure to give class_name and foreign_key b/c ActiveRecord doesn't know what friend is
  belongs_to :friend, :class_name => "Person", :foreign_key => "friend_id"
end

class Person < ActiveRecord::Base
  # tell ActiveRecord that a person has_many friendships or :through won't work
  has_many :friendships

  # create the has_many :through relationship
  has_many :friends, :through => :friendships

  # an example of how to get only the authorized friends
  has_many :authorized_friends, :through => :friendships, :source => :friend, :conditions => [ "authorized = ?", true ]

  # an example of how to get only the unauthorized friends
  has_many :unauthorized_friends, :through => :friendships, :source => :friend, :conditions => [ "authorized = ?", false ]
end