未定义 'items' 为零 class

undefined 'items' for nil class

在我的电子商店网站上,当我尝试结帐我的购物车时,我收到了

undefined method `items' for nil:NilClass. 

虽然在错误页面

我知道我的购物车在那里...但是当我调用它时,它没有给我

购物车模型

 class Cart
   attr_reader :items

    def self.build_from_hash hash
      items = if hash["cart"] then
      hash["cart"]["items"].map do |item_data|
      CartItem.new item_data["product_id"], item_data["quantity"]
       end
       else
         []
       end
        new items
     end

    def initialize items = []
     @items = items
    end

    def add_item product_id
      item = @items.find { |item| item.product_id == product_id }
       if item
         item.increment
       else
         @items << CartItem.new(product_id)
       end
    end

    def empty?
      @items.empty?
    end

    def count
      @items.length
    end

    def serialize
       items = @items.map do |item|
         {
           "product_id" => item.product_id,
           "quantity" => item.quantity
         }
       end
      {
       "items" => items
      }
    end

    def total_price
      @items.inject(0) { |sum, item| sum + item.total_price }
    end


 end

应用程序控制器

     def initialize_cart
        @cart = Cart.build_from_hash session
     end

手推车控制器

 class CartsController < ApplicationController
    before_filter :initialize_cart

   def add
    @cart.add_item params[:id]
    session["cart"] = @cart.serialize
    product = Product.find params[:id]
    redirect_to :back, notice: "Added #{product.name} to cart."
   end

   def show
   end

   def checkout
     @order_form = OrderForm.new user: User.new
   end
 end

订单控制器

  class OrdersController
     def create
       @order_form = OrderForm.new(
       user: User.new(order_params[:user]),
       cart: @cart
      )
      if @order_form.save
       redirect_to '/', notice: "Thank you for placing your order."
       @cart.empty?
      else
       render 'carts/checkout'
      end
     end

结帐视图

 <div class="container-checkout">
    <p class="text-title"> You are checking out the following: </p>
      <table class="table table-striped">
        <thead class="name-table">
          <tr>
            <td> Image </td>
            <td> Name </td>
            <td> Category</td>
            <td> Size </td>
            <td> Item Price </td>
          </tr>
        </thead>
      <tbody>

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

        <tr>
          <td><img src="<%= item.product.image %>" width="50px"></td>
          <td><%= item.product.name.capitalize %></td>
          <td><%= item.product.category.name %></td>
          <td><%= item.product.size %></td>
          <td class="price-item"><%= number_to_currency item.total_price %>
        </td>
        <% end %>
      </tr>
      <tr class="total-price total-price-checkout">
        <td class="name-table">Total Price</td> 
        <td class="price-item"><%= number_to_currency @cart.total_price %></td>
      </tr>
    </tbody>
  </table>

</div>


<div class="details-user-form">
  <%= form_for @order_form, url: orders_path do |f|%>
  <% f.fields_for :user, @order_form.user do |u| %>
    <p class="text-title">Fill the form with your details</p>
    <p><%= render "orders/errors" %></p>
    <p><%= u.text_field :name, placeholder: "Name" %></p>
    <p><%= u.text_field :email, placeholder: "Email" %></p>
    <p><%= u.text_field :address, placeholder: "Address" %></p>
    <p><%= u.text_field :postal_code, placeholder: "Postal code" %></p>
    <p><%= u.text_field :city, placeholder: "City" %></p>
    <p><%= u.text_field :country, placeholder: "Country" %></p>
    <%= f.submit "Place order", class: "order-btn"%><br>
  <% end %>
 <% end %>
</div>

知道为什么要这样做吗?也是因为,它以前工作过..我不知道为什么它停止了。

我认为问题可能是 @cart 变量没有在 OrdersController 中设置。在 CartsController 中设置变量不会使其在全局范围内可用,因为它只会作用于创建它的控制器,在您的例子中是 CartsController

此外,我发现您的 Cart 模型更像是一个虚拟模型,而不是 ActiveRecord 模型,我认为 ActiveRecord 已经具备了您正在寻找的行为您在那里重新创建了很多方法。

我不太确定,但我认为这些可能是问题所在。

更新

我想我发现了你的错误。

在你的 OrdersController 你应该有一个

before_action :initialize_cart

这似乎来自您的 ApplicationController

如果您检查 CartController 中的 checkout 方法,您会发现您没有设置 @cart。因此,当您点击 checkout 视图时,它会在该方法中查找值或 @cart 。将它设置在那里,就像下面的代码应该清除你的错误。

def checkout
  @order_form = OrderForm.new user: User.new
  @cart = # cart object
end