Ruby on rails Rails服务器提升";回收物品“;按对象\u id创建实例时有时会出错

Ruby on rails Rails服务器提升";回收物品“;按对象\u id创建实例时有时会出错,ruby-on-rails,ruby,ajax,nested-forms,Ruby On Rails,Ruby,Ajax,Nested Forms,我的问题是,当使用ajax以Rails的方式动态地添加表单的一部分时,就会出现这种情况。异步请求是在节点对象的事件输入发生时发出的,并且它正在工作。她将dataaction属性中定义的stock\u component\u f.object\u id发送给控制器,并且定义了一个助手方法form\u parent,以便根据部分stock\u component\u字段访问。haml 这是我的表格 = form_for @stock_ingredient, remote: true do |stoc

我的问题是,当使用
ajax
Rails
的方式动态地添加表单的一部分时,就会出现这种情况。异步请求是在
节点
对象的事件
输入
发生时发出的,并且它正在工作。她将
dataaction
属性中定义的
stock\u component\u f.object\u id
发送给控制器,并且定义了一个助手方法
form\u parent
,以便根据部分
stock\u component\u字段访问。haml

这是我的表格

= form_for @stock_ingredient, remote: true do |stock_ingredient_f|
  .field
    = stock_ingredient_f.label "Enable/disable keyboard"
    = check_box :keyboard, :handler

  .field
    = stock_ingredient_f.label "Barcode"
    = text_field :ingredient, :barcode, value: stock_ingredient_f.object.ingredient.try(:barcode), class: "barcode", :'data-action' => ingredient_async_path(form_parent_object_id: stock_ingredient_f.object_id)

  - if @stock_ingredient.stock.present?
    .field
      = stock_ingredient_f.label "Stock"
      = stock_ingredient_f.number_field :stock
      %span.brown-color
        = "(#{@stock_ingredient.ingredient.net_weight_unit})"
这是一个应该动态加载的部分

.ingredient-data

  .field
    %dl
      .line
        %dt
          Ingredient:
        %dd
          = "#{@ingredient.name}"

      .line
        %dt
          Stock:
        %dd.stock
          = "#{MeasurementUnits.humanize_for @ingredient.stock_ingredient.stock, resolve_unit_type(@ingredient.net_weight_unit)}"

  .field
    / the problem is raised here
    = form_parent.label "Stock"
    = form_parent.number_field :stock
    %span.brown-color
      = "(#{@ingredient.net_weight_unit})"

  .field
    = form_parent.submit "Save"
    = form_parent.button "Cancel", type: :reset
这是我的
应用程序\u controller.rb
,其中定义了方法
表单\u parent

class ApplicationController < ActionController::Base
  respond_to :html, :js

  # Prevent CSRF attacks by raising an exception.
  # protect_from_forgery with: :exception

  # when will has it login, change this line
  protect_from_forgery with: :exception, if: Proc.new { |c| c.request.format != 'application/json' }
  protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }

  def form_parent
    ObjectSpace._id2ref(params[:form_parent_object_id].to_i) if params[:form_parent_object_id]
  end
  helper_method :form_parent

  def root
    render "layouts/application", layout: false
  end

  protected

    def id
      params[:id]
    end

    def redirect_for_async_request location
      render js: "window.location='#{location}'"
    end

    def alert message
      render js: "window.alert('#{message}')"
    end

    # def no_cache
    #   if Rails.env.development?
    #     response.headers["Cache-Control"] = "no-cache, must-revalidate, max-age=0"
    #   end
    # end

end
表格

= form_for @stock_ingredient, remote: true do |stock_ingredient_f|
  - store_form stock_ingredient_f

  .field
    = stock_ingredient_f.label "Enable/disable keyboard"
    = check_box :keyboard, :handler

  .field
    = stock_ingredient_f.label "Barcode"
    = text_field :ingredient, :barcode, value: stock_ingredient_f.object.ingredient.try(:barcode), class: "barcode", :'data-action' => ingredient_async_path

  - if @stock_ingredient.stock.present?
    .field
      = stock_ingredient_f.label "Stock"
      = stock_ingredient_f.number_field :stock
      %span.brown-color
        = "(#{@stock_ingredient.ingredient.net_weight_unit})"

您猜对了-具有该对象\u id的对象已被垃圾收集。我不知道你为什么要这样做,但这听起来是个非常糟糕的主意。我不完全清楚什么是
form\u parent
(FormBuilder实例?),但我猜您应该在数据库中传递对象的id,从数据库中获取对象,并使用该id从
form\u中为
字段为
获取新的
FormBuilder
实例


即使您可以使用当前的方法,它也会将您限制为单个rails实例,而任何应用程序的严肃部署都会使用分布在2台或更多服务器上的多个实例

此错误表示您正试图访问已被垃圾收集的对象,这可能是您所怀疑的。发生这种情况是因为对象id来自上一次,并且一旦id发送到浏览器,就不再存在对该对象的引用,因此ruby清理了该对象


尽管这可能并不总是正确的,但最好将每个请求都视为在一个新的、独立的ruby进程中运行。如果希望在请求之间“传递”数据,则必须将其发送到客户端(如果不介意更改数据),或者将其存储在会话中,或者将其存储在数据库中。您不能像这里那样传递对象。

是的,
form\u parent
返回一个
FormBuilder
实例。谢谢。我将它存储在一个类变量中,因为它不是在
会话中创建的。
= form_for @stock_ingredient, remote: true do |stock_ingredient_f|
  - store_form stock_ingredient_f

  .field
    = stock_ingredient_f.label "Enable/disable keyboard"
    = check_box :keyboard, :handler

  .field
    = stock_ingredient_f.label "Barcode"
    = text_field :ingredient, :barcode, value: stock_ingredient_f.object.ingredient.try(:barcode), class: "barcode", :'data-action' => ingredient_async_path

  - if @stock_ingredient.stock.present?
    .field
      = stock_ingredient_f.label "Stock"
      = stock_ingredient_f.number_field :stock
      %span.brown-color
        = "(#{@stock_ingredient.ingredient.net_weight_unit})"