Search code examples
ruby-on-railsruby-on-rails-4controllernomethoderror

NoMethodError undefined method `followers_count' in users/show


I went through Treehouses tutorial on how to set up user friendships on adding and deleting friends. However, now I would like to show how many people that user is following and how many people are following that user. Michael Hartl's RoR tutorial goes over this however, I do not know how to implement his tutorial with Treehouses set up. I am a beginner and I know my controller is incorrect when referencing the users count. I am getting a NoMethodError undefined method `followers_count' in users/show.

Does anyone or has anyone succeeded in doing this? If so any pointers on where to go and look or how I can do this would be greatly appreciated! Thanks.

User / Model

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  has_many :posts
  has_many :user_friendships
  has_many :friends, through: :user_friendships, 
                     conditions: { user_friendships: { state: 'accepted'} }

  has_many :pending_user_friendships, class_name: 'UserFriendship',
                                      foreign_key: :user_id,
                                      conditions: { state: 'pending' }
  has_many :pending_friends, through: :pending_user_friendships, source: :friend





  has_many :requested_user_friendships, class_name: 'UserFriendship',
                                      foreign_key: :user_id,
                                      conditions: { state: 'requested' }
  has_many :requested_friends, through: :pending_user_friendships, source: :friend




  has_many :blocked_user_friendships, class_name: 'UserFriendship',
                                      foreign_key: :user_id,
                                      conditions: { state: 'blocked' }
  has_many :blocked_friends, through: :pending_user_friendships, source: :friend



  has_many :accepted_user_friendships, class_name: 'UserFriendship',
                                      foreign_key: :user_id,
                                      conditions: { state: 'accepted' }
  has_many :accepted_friends, through: :pending_user_friendships, source: :friend



  validates :name, presence: true



  has_one :profile

  belongs_to :user

  has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "150x150>" }, :default_url => "/assets/avatar.png"
  validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/

 def has_blocked?(other_user)
  blocked_friends.include?(other_user)
 end

 def followers_count
    user_friendships.count
  end

  def followed_by_count
    UserFriendship.where(friend_id: self.id).count
  end

end

User / Show. html

 <% provide(:title, @user.name) %>

 <div class="row">
   <aside class="span4">
    <section>
       <h1>
         <%= image_tag @user.avatar.url(:thumb) %>
         <%= @user.name %>
         <%= @user.followers_count%>
         <%= @user.followed_by_count %>
        </h1>
     <div id="friend-status">
       <% if current_user.friends.include?(@user) ||  current_user.pending_friends.include?(@user) %>
          <%= link_to "Edit Friendship",  edit_user_friendship_path(friend_id: @user), class: "btn btn- info btn-sm" %>
       <% else %>
          <%= link_to "Follow",  new_user_friendship_path(friend_id: @user), class: "btn btn- info btn-sm", id: 'add-friendship', data: { friend_id:  @user.to_param } %>
        <% end %>
     </div>
    </section>
    </aside>
</div>

User Friendship Controller

class UserFriendshipsController < ApplicationController
   before_filter :authenticate_user!
   respond_to :html, :json

  def index
  @user_Friendships = UserFriendshipDecorator.decorate_collection(friendship_association.all)
  respond_with @user_Friendships
  end   

 def accept
  @user_friendship = current_user.user_friendships.find(params[:id])
   if @user_friendship.accept_mutual_friendship!
  @user_friendship.friend.user_friendships.find_by(friend_id: current_user.id).accept_mutual_friendship!
  flash[:success] = "You are now friends with #{@user_friendship.friend.name}!"
   redirect_to user_friendships_path
    else
    flash[:error] = "That friendship could not be accepted."
    end
   end

  def block
   @user_friendship = current_user.user_friendships.find(params[:id])
    if @user_friendship.block!
      flash[:success] = "You have blocked #{@user_friendship.friend.name}."
    else
      flash[:error] = "This friendship could not be blocked."
    end
    redirect_to user_friendships_path
  end

  def new
    if params[:friend_id]
      @friend = User.find(params[:friend_id]).first
      raise ActiveRecord::RecordNotFound if @friend.nil?
      @user_friendship = current_user.user_friendships.new(friend: @friend)
    else
      flash[:error] = "Friend required."
    end
  rescue ActiveRecord::RecordNotFound
    render file: 'public/404', status: :not_found
  end

  def create
    if params[:user_friendship] && params[:user_friendship].has_key?(:friend_id)
   @friend = User.find(params[:user_friendship][:friend_id])
   @user_friendship = UserFriendship.request(current_user, @friend)
   respond_to do |format|
     if @user_friendship.new_record?
       format.html do
         flash[:error] = "There was a problem creating this friend request."
         redirect_to user_path(@friend)
       end
       format.json { render json: @user_friendship.to_json, status: :precondition_failed }
        else
        format.html do
          flash[:success] = "Friend request sent."
          redirect_to user_path(@friend)
         end
          format.json { render json: @user_friendship.to_json }
         end
      end
    else
     flash[:error] = "Friend required"
     redirect_to root_path
    end
  end

  def edit
  @friend = User.find(params[:id])
 @user_friendship = current_user.user_friendships.find_by(friend_id: @friend.id).decorate
 end

 def destroy
  @user_friendship = current_user.user_friendships.find(params[:id])
   if @user_friendship.destroy
   flash[:success] = "Your friendship was deleted"
  end  
   redirect_to user_friendships_path
  end

 def user_friendship
   params.require(:user_friendship).permit(:user_id, :friend_id, :user, :friend, :state, :user_friendship)
 end  

  def avatar
  end

  def followers_count
   @user_friendship.find_by_follower_id(friend.id)
  end

  def followed_by_count
   @user_friendship.create!(friend_id: friend.id)
  end

  private
  def friendship_association
    case params[:list]
   when nil
   current_user.user_friendships
   when 'blocked'
   current_user.blocked_user_friendships
   when 'pending'
    current_user.pending_user_friendships
   when 'accepted'
   current_user.accepted_user_friendships
   when 'requested'
   current_user.requested_user_friendships
   end
  end
 end

Solution

  • It looks like you are mixing the User model methods with the relationship model methods. You are calling @user.followers_count which is looking for the followers_count method on user, which does not exist. You have it defined on the UsersFriendships model. You didn't include the User model, but it should look something like this to get rid of this error, though there may be a few more after you get past it.

    class User < ActiveRecord::Base
      has_many :user_friendships
      #everything else
    
      def followers_count
        user_friendships.count
      end
    
      def followed_by_count
        UserFriendship.where(friend_id: self.id).count
      end
    end
    

    You will want to remove the followers_count and followed_by_count from the UserFriendship model. Also, it looks like you have some private methods in the controller as well called followers_count and followed_by_count.