ruby-on-railssocial-network-friendship

Why friendships for social linking in Rails?


Looking at a lot of tutorials on social linking systems in rails. I notice that there seems to be a consistent use of friends as alias for user objects, with a join model "friendships".

I followed this at first, but as I go forward it seems to make things like create.friend really obtuse. Now in my example, I'm using the term "contact" and "connection"...When I'm listing all of a user's contacts, I expect to do this through the contacts controller and views ( /contacts , /contacts/search, /contacts/create, etc.. ) but all the crud really deals with the connection (friendship) table...this starts seeming really backwards as I go.

Why is it done this way? The only benefit I see is being able to say something like "contact.email" But I'm not sure the additional abstraction and gymnastics in my code are worth it. I'd be just as happy to say contact.user.email.

Link to a contacts page? link_to contact.user (right?)

Is there any foul if I just have a model "contacts" with standard, obvious, crud structures and forgo this aliasing of user model? Frankly, I don't see a lot of gain in messing with the user model at all for much more than authentication...I'm putting all info for user in a profile.

Or am I missing something?

UPDATE: I seem to be being unclear, so I'll elaborate.

Plan A:

def contact
 belongs_to :user
 belongs_to :connection, :class_name => 'User', :foreign_key =>'contact_id'
 validates_uniqueness_of :contact_id, :scope => :user_id, :message => ' allready one of your contacts.'
 attr_accessor :invite
end

Then follow with normal CRUD for this. Going to my "contacts" page will show all my contacts with normal crud operations, etc...To get a contact's email, I would, under this scenario say : contact.connection.email

Then I did some reading and saw that everyone else was doing this:

class Connection < ActiveRecord::Base

  belongs_to :user
  belongs_to :contact, :class_name => 'User', :foreign_key =>'contact_id'

  validates_presence_of :user_id
  validates_presence_of :contact_id
  validates_uniqueness_of :contact_id, :scope => :user_id, :message => ' allready one of your contacts.'

  attr_accessor :invite
  end

But then using a Contacts controller (friends controller) to hand the crud here. The only benefit seeming that then you can say contact.email...but it makes all the crud in the contacts controller strange imho. EG:

http://railsforum.com/viewtopic.php?id=16760

I was wondering why the apparent disconnect?

UPDATE 2:

So I get it...a contact has to be a reference to the user model...no getting around that. 3 steps regardless in that event. However I'm still confused on a few of the fine points when I try to execute along this path:

Is it a violation of mvc to have contacts_controller.rb with code like this:

  # in contacts_controller.rb
def destroy 
    @connection = Connection.find(params[:id])
    @connection.destroy

    respond_to do |format|
      format.html { redirect_to :action=>'index' }
      format.xml  { head :ok }
    end  
  end

And then it gets odd when I try to do form_for @connection, routing errors and all. I know I'm kitchen-sinking this question and really appreciate all the feedback so far.

UPDATE 3:

A practical example of the confusion I'm having with these relationships is exemplified here:

<% @contacts.each do |contact| %>
    <li><%= contact.email %> <%= link_to 'Remove Contact', contact.connection, :confirm => 'Are you sure?', :method => :delete %></li>
<% end %>

When iterating through a user's contacts, how can I artfully invoke the connection that brings up this contact in the list to target for delete? Maybe I should just be iterating through a user's connections, pulling the connection.contact.email to display the email?


Solution

  • I'm not sure I fully follow your question, but hopefully this will give you enough to either answer your question is post it in such a way where it's more answerable.

    The reason why you would model the friendship relationship as a join model is that friendships are directional, in so far as "because I have a friendship with you doesn't mean that you have a friendship with me". If you consider the case where I create a friendship with you it's not necessarily valid until you have confirmed the friendship and created the association that points in the other direction.

    Another reason for modelling the friendship as a separate entity is that it lets you enrich the model, so you could also include how you know the person, or even a link to the person who introduced you.

    When you create models you shouldn't necessarily think of them as being 1-1 with controllers. Your resources are separate from your models...

    In many applications you have a user model and a profile model. These often have a 1-1 relationship and people often wonder why they are not modeled as one entity. To be honest, there's no concrete reason as to why you can't model as the same entity but there are a few benefits to keeping them separate. For a start you can delete a users login credentials without deleting their profile (this is great if someone wants to delete their account, but you don't want to/need to delete their content.) For example you delete your facebook account and your tagged photos will still show your name, but not a link to your profile (I don't know if this is actually how it works, it's just an example.) There are also other softer reasons like single responsibility, separation of concerns etc... which are "good practices" and should hopefully make your application easier to maintain.

    I hope this helps a little, if you have any further questions leave a comment and I'll update this post.