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

时间:2018-09-13 07:55:26

标签: ruby-on-rails ruby ajax

我的“新”操作从会话中生成购物车对象@cart。当我通过AJAX调用“更新”操作时,@ cart对象不存在。为什么不跨控制器共享它?

cart_controller.rb

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

def update
  logger.debug @cart.present? # false
end

4 个答案:

答案 0 :(得分:3)

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

基本上,如果您在会话中设置了一些数据,则可以在请求之间使用该数据。如前所述,您可以在执行before_filter操作之前设置@cart和预设update实例变量。

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 :(得分:1)

实例变量(以@开头)在请求之间(或在控制器操作之间)不共享。您可以表示一种获取购物车的方法。这是一个示例:

def new
  cart
end

def update
  logger.debug cart.present?
end

private

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

答案 2 :(得分:0)

实例变量不能在控制器之间共享。它们可用于定义它们的actions。因此,由于未定义@cart操作,因此无法使用update

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

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

DRY 代码,请使用before_action设置购物车

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

答案 3 :(得分:0)

TL; DR:随着每个请求创建一个新的控制器实例,控制器实例变量不会在不同的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

但是,当您向update发出新的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