undefined method `items' for nil:NilClass in @

2019-08-26 18:45发布

问题:

These are my pruduct.rb, cart.eb and item.rb

class Product < ActiveRecord::Base

attr_accessible :category_id, :color, :description, :price, :size, :title, :product_type, :sub_category_id, :image_url

  belongs_to :category
  belongs_to :sub_category
  has_many :items
end  

Cart.rb

class Cart < ActiveRecord::Base

  has_many :items, dependent: :destroy
end  

Item.rb

class Item < ActiveRecord::Base


attr_accessible :cart_id, :product_id,:product

  belongs_to :cart
  belongs_to :product
end  

The ItemContoller

class ItemController < ApplicationController

def create
    @cart=current_cart
    product=Product.find(params[:product_id])
    @item=@cart.items.build(product: product)
    redirect_to clothes_path
    flash.now[:success]="Product successfully added to Cart"
  end

end  

Now in my views when I want to show the cart contents like

<%= @cart.items.each do |item| %>  

The current_cart method

def current_cart
cart=Cart.find(session[:cart_id])
rescue ActiveRecord::RecordNotFound
    cart=Cart.create
    session[:cart_id]=cart.id
    cart
  end

it gives me this error

undefined method `items' for nil:NilClass

What is wrong here?
I'm following the example Agile web Developement with Rails book.

回答1:

after you redirect to cloths_path from ItemController's create action @cart instance variable will not be available to cloth's controller index action. to need to reset it some how in index action

for eg: - 

you can pass cart id to it and find it in index cloth's action

redirect_to clothes_path, card_id: @cart.id

and in cloth's index action do 

@cart = Cart.find params[:cart_id]


create a mathod in application controller, and after u create a new cart, save its id in session, like

session[:cart] = @cart.id

def current_cart
  @cart = Cart.find session[:cart_id]
end

and in view use current_cart method instead of @cart 


回答2:

You're redirecting to clothes_path (redirect_to clothes_path) and it seems you have ClothController. This controller should contain index method to render index page. Assign current_cart to @cart there:

class ClothController < ApplicationController

  def index
    @cart = current_cart
  end

  ...

end

UPDATE

To make @cart available in all views of Cloth controller there is a method before_filter where you can set @cart variable. You can add this definitions in your required controllers. For more details - http://guides.rubyonrails.org/action_controller_overview.html#filters

class ClothController < ApplicationController
  before_filter :set_current_cart

  def index
  end

  ...

  private

  def set_current_cart
    @cart = current_cart
  end

end

current_cart method should be implemented as helper to be available in all controllers. (http://guides.rubyonrails.org/form_helpers.html)


UPDATE 2

Implement a helper in /app/helpers/cart_helper.rb:

module CartHelper

  def current_cart
    # Your current cart method code
  end

end

And include it into required controllers. current_cart method will be available in all views of controllers which contain CartHelper.

class ClothController < ApplicationController
  include CartHelper

  ...
end