Dena
Dena

Reputation: 119

undefined method `each' for nil:NilClass within Pages#friends

I am trying to get my followers to display on the pages/friends however, I keep getting multiple errors like an undefined method `each' for nil:NilClass in my Pages#friends error. I am following Michael Harlts tutorials on follow/unfollow however, I needed to tweak a couple of things because I did not follow the entire thing.

When a user goes to their Friends link (pages/friends) I want it to display everyone who is following them. Like how my users/index displays everyone. Please see my code below. Any help of suggestions would be great.

Pages/friends

<h1>Friends</h1>

<% @user ||= current_user %>
 <% @users.each do |user| %>
     <center><%= link_to image_tag(user.avatar.url(:thumb)), user %></center>
     <strong><center><br><%= link_to user.name, user %></br></center></strong>
     <% if current_user.admin %>
 <% end %>
  <% end %>

Pages/controller

  def home
  end

  def about
  end

  def friends
  end

end

**Users/index*

<% provide(:title, 'All users') %>
<h1>All users</h1>

    <div class="col-md-offset-4 col-med-8">
        <div class="panel panel-default">
        <div class="panel-heading center">

  <% @users.each do |user| %>
     <center><%= link_to image_tag(user.avatar.url(:thumb)), user %></center>
     <strong><center><br><%= link_to user.name, user %></br></center></strong>
     <% if current_user.admin %>

  <% @user ||= current_user %>
      <div class="stats">
        <a href="<%= friends_path(@user) %>">
          <strong id="following" class="stat">
            <%= @user.followed_users.count %>
          </strong>
          following
        </a>
        <a href="<%= friends_path(@user) %>">
          <strong id="followers" class="stat">
            <%= @user.followers.count %>
          </strong>
          followers
        </a>
      </div>


 <center><%= link_to "Delete", user, method: :delete, data: { confirm: "Are you sure?" } %></center>
<% end %>
<% end %>

<div class="center">
<%= will_paginate @users, renderer: BootstrapPagination::Rails %>
</div>
</div>

Routes

devise_for :admins
  devise_for :users

  resources :posts
  resources :users do
    member do
      get :following, :followers
    end
  end

  resources :relationships, only: [:create, :destroy]
  resources :user_friendships do 
      member do
        put :accept
      end
     end   

  get "users/show"


  root "pages#home"
  get 'feed', to: 'posts#index', as: :feed
  get "about" => "pages#about"
  get "friends" => 'pages#friends'


  match 'users/:id' => 'users#show', via: :get
  match 'users/:id' => 'users#index', via: :destroy


  match 'users/:id' => 'users#destroy', via: :get
  match 'users/:id' => 'users#destroy', via: :delete


  get '/:id', to: 'users#show'

Users/controller

class UsersController < ApplicationController

  before_action :correct_user, only: [:edit, :update, :destroy, :following, :followers]
  before_action :authenticate_user!, except: [:index, :show]
  before_action :admin_user,     only: :destroy


  def index
    @users = User.paginate(page: params[:page], :per_page => 5)
  end


  def show
    @user = User.find(params[:id])

    if @user 

        @posts = @user.posts.all
        render actions: :show 
    else
        render file: 'public/404', status: 404, formats: [:html]
    end  

def destroy
    User.find(params[:id]).destroy
    flash[:success] = "Your account has been deleted."
    redirect_to root_path
  end

  def correct_user
      @user = User.find(params[:id])
      redirect_to root_path 
    end

  def admin_user
      redirect_to root_path unless current_user.admin?
  end


  def following
    @title = "Following"
    @user = User.find(params[:id])
    @users = @user.followed_users.paginate(page: params[:page])
    render 'show_follow'
  end

  def followers
    @title = "Followers"
    @user = User.find(params[:id])
    @users = @user.followers.paginate(page: params[:page])
    render 'show_follow'
  end

  end
end

Relationships Controller

class RelationshipsController < ApplicationController

  before_action :authenticate_user!, except: [:index, :show]


def create
    @user = User.find(params[:relationship][:followed_id])
    current_user.follow!(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end

  def destroy
    @user = Relationship.find(params[:id]).followed
    current_user.unfollow!(@user)
    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end
  end

end

Upvotes: 2

Views: 895

Answers (2)

Sam Starling
Sam Starling

Reputation: 5378

The error undefined method 'each' for nil:NilClass means that you're calling .each on an object that is nil.

For example, here, @users could be nil:

def index
  @users = User.paginate(page: params[:page], :per_page => 5)
end

If you then call <% @users.each ... %>, you'll get the undefined method error. You've posted quite a lot of code above, so it's difficult to know exactly where that error is being thrown. Try and work out exactly where the error is being thrown (posting a stack trace would help), and work out which object is nil. Then work out why it's nil - is there no data? Or is your ActiveRecord query returning no results?

Hopefully that gives you some pointers as to where to start looking next.

Edit: As mmichael points out, the error is being caused due to the fact that @users was undeclared in pages#friends. Thanks!

Upvotes: 3

Richard Peck
Richard Peck

Reputation: 76774

As you're new, I'll give you another opinion. What I'm going to write is similar to Sam's answer; I intend to help you appreciate how Rails works, to further your experience


Objects

You must remember that Rails is built on top of Ruby - an object-orientated language. This means every time you declare / use a variable inside Ruby, you're actually accessing an object, which Ruby treats as having a series of methods:

Ruby is pure object-oriented language and everything appears to Ruby as an object. Every value in Ruby is an object, even the most primitive things: strings, numbers and even true and false. Even a class itself is an object that is an instance of the Class class. This chapter will take you through all the major functionalities related to Object Oriented Ruby.

I write this because Ruby's object-orientated structure is much different than handling variables in the "traditional" sense -- in the simplest description, it means that Ruby presumes that objects are ALWAYS present (it just builds them from the NilClass), allowing you call "empty" data sets without running into "undeclared" issues

The problems occur when you try and run methods like .each on empty / nil objects. If you do this, errors like the one you alluded to occur; preventing you from being able to perform the functionality which you intended

--

Fix

Your error basically means you haven't declared your variable.

After seeing your code, the most obvious problem will be here:

#app/controllers/pages_controller.rb
Class PagesController < ApplicationController
   def friends
       # normally, you'd define your @instance_variables here
   end
end

I see that your friends action does not declare your @users variable, which is required to perform the @users.each method. As recommended by Sam, the first step is to ensure you're able to declare this value, allowing you to loop through it as required:

#app/controllers/pages_controller.rb
Class PagesController < ApplicationController
   def friends
      @users = User.all
   end
end

Upvotes: 1

Related Questions