user1107922
user1107922

Reputation: 610

Rails, nil object error

I have Categories controller and in layout _menu.html.erb I want to output all categories in home page but I have this error message:

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each

When I logged as a administrator I can add, edit, delete and view all categories.

This is part of my code:

_menu.html.erb

<div class="menu">
  <% @categories.each do |category| %>
    <li>
      <%= link_to category.title, category %>
    </li>
  <% end %>
</div>

Categories_controller.rb

  def index
    @title = "All categories"
    @categories = Category.paginate(:page => params[:page])
  end

  def show
    @category = Category.find(params[:id])
    @title = @category.title
  end

  def new
    @category = Category.new
    @title = "Add category"
  end

  def create
    @category = Category.new(params[:category])
   if @category.save
     flash[:success] = "Successfully added category"
     redirect_to categories_path
   else
     @title = "Sign up"
     render 'new'
   end
 end

 def edit
   @category = Category.find(params[:id])
   @title = "Edit category"
 end

 def update
   @category = Category.find(params[:id])
   if @category.update_attributes(params[:category])
     flash[:success] = "Category updated."
     redirect_to categories_path
   else
     @title = "Edit user"
     render 'edit'
   end
 end

 def destroy
   Category.find(params[:id]).destroy
   flash[:success] = "User destroyed."
   redirect_to categories_path
 end

end

Upvotes: 0

Views: 261

Answers (1)

iltempo
iltempo

Reputation: 16012

@categories are defined only in the index action. I'm assuming you are using the _menu.html.erb as a partial in the layout - on every page.

The @categories will be nil for the others which will cause the exception.

There are basically two ways to define categories for all actions. One would be to do the call in the partial like

<% Category.all.each do |category| %>

The other way using a before filter in your controller

class CategoriesController
  before_filter :load_categories

  ...

  private

  def load_categories
    @categories = Category.all
  end
end

I personally prefer the second way because I don't like database calls triggered in views.

Upvotes: 3

Related Questions