#163 Self-Referential Association
May 25, 2009 | 14 minutes | Active Record, Controllers
Creating a social networking site often requires a self-referential association on the User model to define friends/followers. In this episode I show how to do exactly that.
- Download:
- source codeProject Files in Zip (99 KB)
- mp4Full Size H.264 Video (21.1 MB)
- m4vSmaller H.264 Video (14.8 MB)
- webmFull Size VP8 Video (41.1 MB)
- ogvFull Size Theora Video (30.3 MB)
Resources
bash
script/generate nifty_scaffold friendship user_id:integer friend_id:integer create destroy
rake db:migrate
script/generate nifty_scaffold friendship user_id:integer friend_id:integer create destroy rake db:migrate
models/user.rb
has_many :friendships
has_many :friends, :through => :friendships
has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id"
has_many :inverse_friends, :through => :inverse_friendships, :source => :user
has_many :friendships has_many :friends, :through => :friendships has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id" has_many :inverse_friends, :through => :inverse_friendships, :source => :user
models/friendship.rb
belongs_to :user
belongs_to :friend, :class_name => "User"
belongs_to :user belongs_to :friend, :class_name => "User"
friendships_controller.rb
def create
@friendship = current_user.friendships.build(:friend_id => params[:friend_id])
if @friendship.save
flash[:notice] = "Added friend."
redirect_to root_url
else
flash[:error] = "Unable to add friend."
redirect_to root_url
end
end
def destroy
@friendship = current_user.friendships.find(params[:id])
@friendship.destroy
flash[:notice] = "Removed friendship."
redirect_to current_user
end
def create @friendship = current_user.friendships.build(:friend_id => params[:friend_id]) if @friendship.save flash[:notice] = "Added friend." redirect_to root_url else flash[:error] = "Unable to add friend." redirect_to root_url end end def destroy @friendship = current_user.friendships.find(params[:id]) @friendship.destroy flash[:notice] = "Removed friendship." redirect_to current_user end
users/index.html.erb
<%= link_to "Add Friend", friendships_path(:friend_id => user), :method => :post %>
<%= link_to "Add Friend", friendships_path(:friend_id => user), :method => :post %>
users/show.html.erb
<h2>Friends</h2>
<ul>
<% for friendship in @user.friendships %>
<li>
<%=h friendship.friend.username %>
(<%= link_to "remove", friendship, :method => :delete %>)
</li>
<% end %>
</ul>
<p><%= link_to "Find Friends", users_path %></p>
<h2>Friended by Users</h2>
<ul>
<% for user in @user.inverse_friends %>
<li><%=h user.username %></li>
<% end %>
</ul>
<h2>Friends</h2> <ul> <% for friendship in @user.friendships %> <li> <%=h friendship.friend.username %> (<%= link_to "remove", friendship, :method => :delete %>) </li> <% end %> </ul> <p><%= link_to "Find Friends", users_path %></p> <h2>Friended by Users</h2> <ul> <% for user in @user.inverse_friends %> <li><%=h user.username %></li> <% end %> </ul>

