我的问题是在ajax
的方式添加{strong>动态的部分内容时发生了Rails
。异步请求是在input
对象的事件Node
发生时生成的,并且它可以正常工作。她将stock_ingredient_f.object_id
属性中定义的data-action
发送给控制器,并且根据部分form_parent
定义了辅助方法_stock_ingredient_fields.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
这是我的application_controller.rb
,其中定义了方法form_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
刷新页面并再次触发请求时,服务器会说:ActionView::Template::Error (0x002ac5927b9058 is recycled object)
可能会引用ObjectSpace._id2ref
的响应。
我相信收集了垃圾收集器。
UPDATE application_controller.rb
def form_parent
@@form_parent
end
def store_form object
@@form_parent = object
end
helper_method :form_parent, :store_form
形式
= 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})"
答案 0 :(得分:1)
此错误表示您正在尝试访问已被垃圾收集的对象,您可能已怀疑。发生这种情况是因为对象id来自上一次,并且一旦id被发送到浏览器,就不再存在对该对象的引用,因此ruby清理了该对象。
尽管可能并非总是如此,但最好将每个请求视为在新的单独ruby进程中运行。如果要在请求之间“传递”数据,则必须将其发送到客户端(如果您不介意更改数据)或将其存储在会话中,或将其存储在数据库中。你不能像在这里那样传递物体。
答案 1 :(得分:0)
您怀疑是正确的 - 具有该object_id的对象已被垃圾收集。我不确定你为什么要这样做,但这听起来真的很糟糕。我不完全清楚form_parent
是什么(FormBuilder实例?)但是猜测你应该传递数据库中对象的id,从数据库中获取对象并使用它来获得一个新的{来自FormBuilder
或form_for
的{1}}实例。
即使您可以使当前的方法工作,它也会限制您使用单个rails实例,而任何严重的应用程序部署都会使用分布在2个或更多服务器上的多个实例。