我的“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
我的“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
@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
实例变量(以@
开头)不会在请求之间共享(或跨控制器操作)。您可以指定一个方法来获取购物车。以下是一个示例:
def new
cart
end
def update
logger.debug cart.present?
end
private
def cart
@cart ||= Cart.new(session[:cart])
end
before_action
来创建@cart
实例,这样@cart
实例变量将对new
和update
操作可见。before_action :get_cart, only: [:new, :update]
private
def get_cart
@cart = Cart.new(session[:cart])
end
如果您不想使用动作回调,另一个选择是直接调用get_cart
方法到new
和update
操作中。因为,get_cart
返回实例@cart
。关于这一点,请参见link。
实例变量不能在控制器之间共享。它们只能在定义它们的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
简而言之:控制器实例变量在不同的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
正如您所看到的,controller
和controller1
是从MyController
初始化的两个不同对象,因为它们发生在两个不同的HTTP请求(不同的上下文)中。
要解决您的问题,您需要在每个操作中创建@cart
,例如:
def new
cart
end
def update
logger.debug cart.present?
end
private
def cart
@cart ||= Cart.new(session[:cart])
end