StoreController#display_cart中的NoMethodError

时间:2015-07-28 13:13:45

标签: ruby-on-rails ruby ruby-on-rails-4

我正在阅读“使用Rails进行敏捷Web开发 - 实用指南”一书。在迭代C1上,创建一个购物车,我收到以下错误:

self.hotlineViewHeightConstraint.constant = 0.0f;

以下是源文件:

的routes.rb

NoMethodError in StoreController#display_cart
undefined method `items' for #<Hash:0xb5cf041c>

Extracted source (around line #15):

13  def display_cart
14    @cart = find_cart
15    @items = @cart.items
16  end
17
18 private

store_controller.rb

Rails.application.routes.draw do
  get 'store' => 'store#index'
  get 'add_item_to_cart' => 'store#add_to_cart'
  get 'display_cart' => 'store#display_cart'
  resources :products

cart.rb

class StoreController < ApplicationController
  def index
    @products = Product.salable_items
  end

  def add_to_cart
    product = Product.find(params[:id])
    @cart = find_cart
    @cart.add_product(product)
    redirect_to display_cart_path
  end

  def display_cart
    @cart = find_cart
    @items = @cart.items
  end

  private 

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

line_item.rb

class Cart
    attr_reader :items
    attr_reader :total_price

    def initialize
        @items = []
        @total_price = 0.0
    end

    def items
        @items
    end

    def add_product(product)
        @items << LineItem.for_product(product)
        @total_price += product.price
    end
end

我从class LineItem < ActiveRecord::Base belongs_to :product def self.for_product(product) item = self.new item.quantity = 1 item.product = product item.unit_price = product.price item end end 的{​​{1}}行动中找到了display_cart行动。即使add_to_cart中有StoreController,为什么我会收到def items

4 个答案:

答案 0 :(得分:1)

问题在于

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

您的session[:cart]是一个哈希,因此无法获得Cart.new,当您致电@cart.items时,Hash就会调用Cart而不是{{1}}对象

答案 1 :(得分:1)

在你的display_cart方法中:你正在做@cart = find_cart,它可能会返回一个哈希而不是一个对象,就像你正在进行的session[:cart] ||= Cart.new的find_cart方法一样,它可能会返回一个哈希。

答案 2 :(得分:1)

假设您已在会话中存储了购物车ID,您可以在方法中执行以下更改

def find_cart
    Cart.find_by_id(session[:cart_id]) ||= Cart.new
end

答案 3 :(得分:1)

尝试此操作以返回您的购物车实例:

def find_cart
  Cart.find(session[:cart]
rescue ActiveRecord::RecordNotFound
  cart = Cart.new
  session[:cart] = cart.id
end

这几乎与您书中的代码相同。在语义上你可以调用该函数current_cart

通过仅存储购物车ID并使用ActiveRecord find()方法,通过调用Cart.new进行救援,您将始终返回购物车实例。

修改

如果你没有将Cart作为模型实现,你将(逻辑上)永远不能实例化它的对象。

This是关于在Ruby on Rails中处理会话的好文章。正如您将看到的,会话本身就是一个“自然”的哈希,你会发现一些替代解决方案,用于在rails应用程序中存储会话。