Friendship System Rails 3.0

I am trying to develop a friendship system like facebook. I have follow
for guidance the two following sources

How to Implement a Friendship Model in Rails 3 for a Social Networking
Application?
Railsspace book chapter 14, which can only be downloaded i believed
I am a bit confused on the way railsspace has been building there
relationship. What i am trying to do his to show in a views my
pending_request, accepted_request and declined_request. The books seem
to suggest the following relationship

FriendshipModel

class Friendship < ActiveRecord::Base
  belongs_to :customer
  belongs_to :friend, :class_name => 'Customer', :foreign_key =>
'friend_id'
CustomerModel

class Customer < ActiveRecord::Base
#RELATIONSHIP
    has_many :friendships
    has_many :friends, :through => :friendships,
         :conditions => "status = 'accepted'"
    has_many :requested_friends,
         :through => :friendships,
         :source => :friend,
         :conditions => "status = 'requested'"
    has_many :pending_friends,
         :through => :friendships,
         :source => :friend,
         :conditions => "status = 'pending'"
The issues i am having his how can i access friends who are pendings,
friends who are requested. I have the following view in my index
(friendship/index)

<div><h1>Request</h1></div>
<table>
  <% @customer.friends.each do |friend| %>
  <tr>
    <td><%= link_to friend.first_name, '#' %></td>
  </tr>
  <% end %>
</table>
But i get the following errors

NoMethodError in Friends#index

Showing /app/views/friends/index.html.erb where line #15 raised:

undefined method `friends' for #<Array:0xb6144040>
Extracted source (around line #15):

12:
13: <div><h1>Request</h1></div>
14: <table>
15: <% @customer.friends.each do |friend| %>
16: <tr>
17: <td><%= link_to friend.first_name, '#' %></td>
18: </tr>
Mind you, my model is called friendship, my controller his called
friends ( not the best name but its more for practise learning I did)

Here the model

# Table name: friendships

undefined method `friends' for #<Array:0xb6144040>

You didn't show us the controller code that defines @customer but I'll bet you used something returned an array when you wanted a single object.

Also, be sure to note that Rails 3.1 finders return ARels (active record relation objects) which are array-like, pre-Rails 3.1 you get an actual array. So you get some funny business when upgrading from pre-Rails 3.1 to Rails 3.1 or higher when doing stuff like this, because ARels can behave like Arrays but aren't actually arrays.

Jason Fb wrote in post #1072568:

undefined method `friends' for #<Array:0xb6144040>

You didn't show us the controller code that defines @customer but I'll
bet you used something returned an array when you wanted a single
object.

Interesting about the Arel thing but here the controller

class FriendsController < ApplicationController

  before_filter :setup_friends

  def index
    @customer = Customer.all
  end

  #Send a friend request
  def create
    Friends.request(@customer, @friend)
  end

  private
    def setup_friends
      @customer = current_customer
      @friend = Customer.find_by_id(params[:id])
    end
end

You seem to have defined @customer twice, once in the setup_friends method which is run first as a before_filter hook, and then again in the index method. the one in the index method returns an array, since you asked for @customer.all

Jason Fb wrote in post #1072573:

You seem to have defined @customer twice, once in the setup_friends
method which is run first as a before_filter hook, and then again in the
index method. the one in the index method returns an array, since you
asked for @customer.all

Sorry for the late reply, after notice I did change many thing. ( redid
from scracth)

So here an updated code

Friendship Model ( and rename table to friendship )
class Friendship < ActiveRecord::Base

  belongs_to :customer
  belongs_to :friend, :class_name => 'Customer', :foreign_key =>
'friend_id'

  validates_presence_of :customer_id, :friend_id
  attr_accessible :approved, :customer_id, :friend_id

#Method
  # Return true if the customers are (possibly pending) friends.
  def self.exists?(customer, friend)
    not find_by_customer_id_and_friend_id(customer, friend).nil?
  end

  # Record a pending friend request.
  def self.request(customer, friend)
    unless customer == friend or Friendship.exists?(customer, friend)
      transaction do
  create(:customer => customer, :friend => friend, :status => 'pending')
  create(:customer => friend, :friend => customer, :status =>
'requested')
      end
    end
  end

  # Accept a friend request.
  def self.accept(customer, friend)
    transaction do
      accepted_at = Time.now
      accept_one_side(customer, friend, accepted_at)
      accept_one_side(friend, customer, accepted_at)
    end
  end

  # Delete a friendship or cancel a pending request.
  def self.breakup(customer, friend)
    transaction do
      destroy(find_by_customer_id_and_friend_id(customer, friend))
      destroy(find_by_customer_id_and_friend_id(friend, customer))
    end
  end

  private

  # Update the db with one side of an accepted friendship request.
  def self.accept_one_side(customer, friend, accepted_at)
    request = find_by_customer_id_and_friend_id(customer, friend)
    request.status = 'accepted'
    request.accepted_at = accepted_at
    request.save!
  end
end

Customer Model
class Customer < ActiveRecord::Base
...
#RELATIONSHIP

  has_many :friendships
  has_many :friends, :through => :friendships,
     :conditions => "status = 'accepted'"
  has_many :requested_friends,
     :through => :friendships,
     :source => :friend,
     :conditions => "status = 'requested'"
  has_many :pending_friends,
     :through => :friendships,
     :source => :friend,
     :conditions => "status = 'pending'"
end

Controller Friendship
class FriendshipsController < ApplicationController

  before_filter :setup_friends

  def accept
    if @customer.requested_friends.include?(@friend)
      Friendship.accept(@customer, @friend)
      flash[:notice] = "Friendship Accepted"
    else
      flash[:notice] = "No Friendship request"
    end
    redirect_to root_url
  end

  def decline
    if @customer.requested_friends.include?(@friend)
      Friendship.breakup(@customer, @friend)
      flash[:notice] = "Friendship Declined"
    else
      flash[:notice] = "No Friendship request"
    end
    redirect_to root_url
  end

  def cancel
    if @customer.pending_friends.include?(@friend)
      Friendship.breakup(@customer, @friend)
      flash[:notice] = "Friendship Canceled"
    elserequested
      flash[:notice] = "No Friendship request"
    end
    redirect_to root_url
  end

  def delete
    if @customer.friends.include?(@friend)
      Friendship.breakup(@customer, @friend)
      flash[:notice] = "Friendship Deleted"
    else
      flash[:notice] = "No Friendship request"
    end
    redirect_to root_url
  end

  def index
    @customers = Customer.all
  end

  #Send a friendship request
  def create
    Friendships.request(@customer, @friend)
  end

  private
    def setup_friends
      @customer = current_customer
      @friend = Customer.find_by_id(params[:id])
    end
end

Now here the issue i seem to not really understand but is to manager the
relationship and here my code atm.
This is in index.html.erb from friendship and list everything,
<div><h1>Friends</h1></div>

<% @customer.friends.each do |friend| %>
  <%= link_to friend.incomplete_name, '#' %><br />
<% end %>

<div><h1>Request</h1></div>

<% @customer.requested_friends.each do |rf| %>
  <%= link_to rf.incomplete_name, '#' %><br />
<% end %>

<div><h1>Pendings</h1></div>

<% @customer.pending_friends.each do |pf| %>
  <%= link_to pf.incomplete_name, '#' %><br />
<% end %>

<div><h1>Users</h1></div>
<% @customers.each do |customer| %>
  <% if current_customer != customer %>
  <div><%= friendship_status(current_customer, customer) %></div>
    <% unless Friendship.exists?(current_customer, customer) %>
      <%= link_to "Request friendship with #{customer.first_name}",
    { :controller => "friendships", :action => "create",
  :id => customer.id },
  :confirm =>
  "Send friend request to #{customer.incomplete_name}?" %>
      <% end %>
  <% end %>
<% end %>

In railspace they use an email link to accept, but i don't want to send
an email and not sure how to refresh page with the proper information.

Thanks in advance

I doubt whether anyone has time to wade through all that code in order
to understand your problem (though I may be proved wrong). You must
try to ask a more specific question.

Colin

Colin Law wrote in post #1072687:

I doubt whether anyone has time to wade through all that code in order
to understand your problem (though I may be proved wrong). You must
try to ask a more specific question.

Colin

I understand and didn't want at first because its a lot of code, but
just wanted to make sure it was understood properly ( language barrier
sometime). Anyway

I am trying to create a relationship among the users, in my controller I
have 2 function create and accept.

When clicking in my view file I have link_to which create the
friendship.
<%= link_to "Request friendship with #{customer.first_name}",
    { :controller => "friendships", :action => "create",
  :id => customer.id },
  :confirm =>
  "Send friend request to #{customer.incomplete_name}?" %>

However I do not see when refreshing that a friendship has really been
created. In what ever states

I believe the issue is here

  has_many :requested_friends,
     :through => :friendships,
     :source => :friend,
     :conditions => "status = 'requested'"

I am just suppose to say @customer.requested_friends and this would
allow me iterate through each of them??

Thanks again

Colin Law wrote in post #1072687:

I doubt whether anyone has time to wade through all that code in order
to understand your problem (though I may be proved wrong). You must
try to ask a more specific question.

Colin

I understand and didn't want at first because its a lot of code, but
just wanted to make sure it was understood properly ( language barrier
sometime). Anyway

I am trying to create a relationship among the users, in my controller I
have 2 function create and accept.

When clicking in my view file I have link_to which create the
friendship.
<%= link_to "Request friendship with #{customer.first_name}",
    { :controller => "friendships", :action => "create",
  :id => customer.id },
  :confirm =>
  "Send friend request to #{customer.incomplete_name}?" %>

Are you using a GET request to create records in the database? This
is generally considered a bad idea.

However I do not see when refreshing that a friendship has really been
created. In what ever states

So has it been created or not? Look directly at the database if
necessary, to check. If not then get that working first before
worrying about any views. Run
rails console
then you can do things like
Friendship.all
and it will show them all. In addition you can run any ruby code to
interrogate the db in the same way as you do in the app (using find
and so on).

I believe the issue is here

  has_many :requested_friends,
     :through => :friendships,
     :source => :friend,
     :conditions => "status = 'requested'"

I am just suppose to say @customer.requested_friends and this would
allow me iterate through each of them??

Yes, but check first as I said above that you are creating the
friendships correctly first. I am sure I have pointed you to the
Rails Guide on debugging already, but if not then have a look at it.

Colin