Ruby on Rails控制器实例变量未共享

3

我的“new”操作通过session生成购物车对象@cart。当我通过AJAX调用“update”操作时,@cart对象不存在。为什么它不能在控制器之间共享?

cart_controller.rb

def new
  @cart = Cart.new(session[:cart])
end

def update
  logger.debug @cart.present? # false
end
5个回答

5

@cart是一个实例变量,不会在请求之间保留。而session可以在请求之间访问。

基本上,如果您已经将某些数据设置到会话中,则可以在请求之间使用该数据。正如所提到的,您可以设置一个before_filter并在执行update操作之前预设@cart实例变量。

class MyController < ApplicationController
  before_action :instantiate_cart, only: [:update] #is the list of actions you want to affect with this `before_action` method
  ...
  private

  def instantiate_cart
    @cart = Cart.new(session[:cart])
  end
end

1

实例变量(以@开头)不会在请求之间共享(或跨控制器操作)。您可以指定一个方法来获取购物车。以下是一个示例:

def new
  cart
end

def update
  logger.debug cart.present?
end

private

def cart
  @cart ||= Cart.new(session[:cart])
end

0
我建议使用before_action来创建@cart实例,这样@cart实例变量将对newupdate操作可见。
before_action :get_cart, only: [:new, :update]

private
def get_cart
  @cart = Cart.new(session[:cart])
end 

如果您不想使用动作回调,另一个选择是直接调用get_cart方法到newupdate操作中。因为,get_cart返回实例@cart。关于这一点,请参见link


0

实例变量不能在控制器之间共享。它们只能在定义它们的actions中使用。因此,您不能在update操作中使用@cart,因为您没有定义它。

def new
  @cart = Cart.new(session[:cart])
end

def update
  @cart = Cart.new(session[:cart])
  logger.debug @cart.present?
end

使用before_action设置购物车,以使代码更加DRY。
before_action :set_cart, only: [:new, :update]

def new
end

def update
  logger.debug @cart.present?
end

private
def set_cart
  @cart = Cart.new(session[:cart])
end

0

简而言之:控制器实例变量在不同的HTTP请求中不共享,因为每个请求都会创建一个新的控制器实例。

从概念上讲,您期望的应该是正确的!您正在定义一个实例变量,并且应该可以在类的任何地方访问它。

问题在于,在每个HTTP请求上,都会创建该类的新实例。

因此,当您点击new操作时,将初始化控制器的一个实例,调用new方法并创建和分配@cart。就像这样:

# HTTP request /new
controller = MyController.new # an object of your controller is created
controller.new # the requested action is called and @cart is assigned

但是当您发起新的HTTP请求以更新时,将初始化控制器的新实例,调用update方法并且它没有@cart

# HTTP request /update
controller1 = MyController.new # an object of your controller is created
controller1.new # the requested action is called and @cart is not assigned 

正如您所看到的,controllercontroller1是从MyController初始化的两个不同对象,因为它们发生在两个不同的HTTP请求(不同的上下文)中。

要解决您的问题,您需要在每个操作中创建@cart,例如:

def new
  cart
end

def update
  logger.debug cart.present?
end

private

def cart
  @cart ||= Cart.new(session[:cart])
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接