Undefined method `items' for nil:NilClass

Hi everybody…

I would appreciate it very much if someone can guide me in the right
direction in solving this problem I have been experiencing.

The section I am working on involves the creation of a shopping cart…

I am following the guide in “Agile web development with rails”. It was
working before, but then the application needed some AJAX and also two
of the views needed to be converted to partials.

Now I can’t get it to work anymore…

It is bound to be some small problem somewhere that I have been blind
to…

It occurs when I try to load the store index page…

Error Message*******

NoMethodError in Store#showmakes

Showing app/views/store/_cart.html.erb where line #3 raised:

undefined method `items’ for nil:NilClass

Extracted source (around line #3):

1:

Your Cart

2:
3: <%= render(:partial => “cart_item”, :collection => cart.items) %>
4:
5:
6:

Trace of template inclusion: app/views/layouts/cameras.html.erb

store index(Working)*****

Your Pragmatic Catalog

<% if @cameras.count > 1 then %>
<% @cameratypes.each do |camera| -%>
<% @firstoftype = find_first_image_in_type(camera.camtype)%>
<%= link_to(image_tag(@firstoftype.image_url), showmakes_url(:id =>
camera.camtype)) %>

<%=h @firstoftype.image_url + ' ' + camera.camtype%>

<% end %> <% end %>

_cart partial***

Your Cart
Total
<%= render(:partial => "cart_item", :collection => cart.items) %>
Total <%= number_to_currency(cart.total_price) %>

<%= button_to ‘Empty cart’, :action => ‘empty_cart’ %>

*****_cart_item partial

<%= cart_item.quantity %> × <%=h cart_item.make %> <%=h cart_item.model %> <%= number_to_currency(cart_item.price) %>

****add_to_cart.js.rjs

page.replace_html(“cart”, :partial => “cart”, :object => @cart)

showmakes view

Your Pragmatic Catalog

<% @camerasbytype.each do |camera| -%>

<% @firstofmake = find_first_image_in_make(camera.make)%> <%= link_to(image_tag(@firstofmake.image_url), showmodels_url(:typeid => camera.camtype, :makeid => camera.make)) %>

<%=h camera.make%>

<% end %>

****showmodels view

<% @cameramodels.each do |camera| -%>

<%= image_tag(camera.image_url) %>

<%=h camera.model%>

<%=h camera.description %>

<%= number_to_currency(camera.price) %> <% form_remote_tag :url => {:action => 'add_to_cart', :id => camera } do %> <%= submit_tag "Add to Cart" %> <% end %>
<% end %>

*******store controller

class StoreController < ApplicationController

helper_method :find_first_image_in_type, :find_first_image_in_make

def index
@cameras = Camera.find_cameras_for_sale
@cameratypes = Camera.find_cameras_by_camtype
end

def find_first_image_in_type(camtype)
Camera.find_first_type_image(camtype)
end

def find_first_image_in_make(cammake)
Camera.find_first_make_image(cammake)
end

def showmakes
@camtype = params[:id]
@camerasbytype = Camera.find_cameras_of_type(@camtype)
end

def showmodels
@camtype = params[:typeid]
@cammake = params[:makeid]
@cameramodels = Camera.find_cameras_by_make_and_type(@camtype,
@cammake)
@cart = find_cart
end

def add_to_cart
camera = Camera.find(params[:id])
@cart = find_cart
@cart.add_camera(camera)
respond_to do |format|
format.js
end
redirect_to_index
rescue
logger.error(“Attempt to access invalid camera #{params[:id]}”)
redirect_to_index(“Invalid camera”)
end

def empty_cart
session[:cart] = nil
redirect_to_index(“Your cart is currenty empty”)
end

private
def find_cart
session[:cart] ||= Cart.new
end

def redirect_to_index(msg = nil)
flash[:notice] = msg if msg
redirect_to :action =>‘index’
end
end


I don’t want to shower you with unnecessary code… It is difficult for
me to trace the error to a specific model, view or controller… So
please if you can’t determine the problem from the code provided… Let
me know and I will give you more information

The important line to start at is where the error says:

Showing app/views/store/_cart.html.erb where line #3 raised:
undefined method `items’ for nil:NilClass

So you know that on line 3 of that file, you’re accessing the .items
method of an object, but that object is actually nil… when you
probably expect it to be an instance of something.

Line 3 says:

3: <%= render(:partial => “cart_item”, :collection => cart.items) %>

so we’re looking at the “cart.items” - and can safely assume that
“cart” isn’t actually a Cart object (or whatever it needs to be), but
is in fact nil. Since this is a partial - you probably have a line in
your index.html.erb file which renders the partial, passing a Cart to
it.

Looking at the controller’s index method (that’s where you said it was
failing), we can see that there’s no definition for the @cart:

def index
@cameras = Camera.find_cameras_for_sale
@cameratypes = Camera.find_cameras_by_camtype
end

So you might benefit from putting a line “@cart = find_cart” in there.
On the flip side (because there’s a couple of gaps in the code you
posted), it may be that “cart” in the partial actually needs to be
@cart”.
Try one change first. If it doesn’t work, back it out and try the
other. If it still doesn’t work, try them both :wink:

Failing that, post back again, and I’ll have a look in my copy of the
book to see what it should be…

Very good suggestion Michael… Thanks for your help… I have deviated a
little from the book, since there are more functions that I need to
incorporate… I tried putting the @cart.find_cart in the index def in
the store controller, but no luck… I believe the add_to_cart.js_rjs
renders the cart partial. Don’t no why the index would render or look
for it…

The add_to_cart function in the store controller is called by a button
on the page ‘showmodels’. In the handbook the @cart.find_item is
located in the add_to_cart function