此特定方法导致应用程序中断:
# needed becasuse of a rails bug
def to_s
"#{self.class.name.underscore}__#{object_id}"
end
出现以下错误:
ActionView::TemplateError (`@content_for_details_view_builder__2234321380' is not allowed as an instance variable name) in app/views/shared/_details_view.haml:
基本上这是导致上述异常的代码执行:
# controller
def new
@view_mode = :new
template = "new"
render template, :layout => false
end
# new.haml
- details_view @user do |b, f|
# build_helper
def details_view(model, options = {}, &block)
# instantiate OptionsWrapper passing a hash of key/value pairs, in this case
# an empty hash. OptionsWrapper contains a method_missing method so when we
# invoke mode on our instance of OptionsWrapper, since it does not contain
# instance method of mode, it invokes method_missing and we set a number of
# methods on fly.
options = OptionsWrapper.new(options)
options.mode ||= @view_mode
model_name = model.class.model_name.singular.dasherize
options.dom_id = "#{model_name}-details-view"
# we instantiate DetailsViewBuilder passing in a few arguments (e.g. new,
# ActionView, user) to the constructor method.
builder = DetailsViewBuilder.new(options.mode, self, model)
options.html ||= {}
options.html[:id] ||= nil
options.html[:class] = "x-#{options.mode} #{options.html[:class]}".strip
render :layout => "shared/details_view", :locals => {:builder => builder,
:model => model, :options => options}, &block
end
#details_view_builder
class DetailsViewBuilder
attr_accessor :mode, :template, :model, :form
def initialize(mode, template, model)
@mode, @template, @model = mode, template, model #new, ActionView, user
end
def to_s
# here's the method causing error!
"#{self.class.name.underscore}__#{object_id}"
end
end
# we then render the details_view passing in some locals as shown a
# few lines above:
.details-dialog{:id => options.dom_id }
case options.mode
- when :new
- form_for model, options.slice(:url, :html) do |form|
= yield builder, form
我百分百确定to_s方法导致错误。我不确定它在哪里被调用它导致了这个错误。请注意,它会生成构建器变量。该构建器变量包含具有此方法的类。我需要找到一种更好的方法来检查元素,这样我就可以透明地看到callstack,并且给定一个方法,我知道它在哪里被调用。奇怪的是,此方法适用于我的本地计算机,但会导致服务器上的生产出错。这是回溯的一小步:
ActionView::TemplateError
(`@content_for_details_view_builder__-626960428' is not allowed as an
instance variable name) in app/views/shared/_details_view.haml:
searchlogic (2.4.27) lib/searchlogic/rails_helpers.rb:75:in
`fields_for'
searchlogic (2.4.27) lib/searchlogic/rails_helpers.rb:64:in
`form_for'
app/helpers/builders_helper.rb:68:in `details_view'
/home/app-sptr/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/benchmark.rb:308:in
`realtime'
app/other/restful_component.rb:488:in `new_html'
app/other/restful_component.rb:73:in `new'
app/other/restful_component.rb:72:in `new'
/home/app-sptr/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/benchmark.rb:308:in
`realtime'
rack (1.1.2) lib/rack/head.rb:9:in `call'
rack (1.1.2) lib/rack/methodoverride.rb:24:in `call'
rack (1.1.2) lib/rack/lock.rb:11:in `call'
rack (1.1.2) lib/rack/lock.rb:11:in `synchronize'
rack (1.1.2) lib/rack/lock.rb:11:in `call'
我在这里也提出了问题,但对答案不满意: http://www.ruby-forum.com/topic/1641800#new
答案 0 :(得分:5)
建议使用caller()
可以从某种方法中找出堆栈跟踪。但是,我也会分享(我认为)解决问题的方法。
to_s
方法返回一个字符串,用于动态设置实例变量。 DetailsViewBuilder
的{{1}}是变量名称的一部分。对象ID表示对象在内存中的位置。与直觉相反,对象的 object_id
有时可能是负整数。是否发生这种情况也可能依赖于平台。这解释了为什么您只在生产中看到此错误。负对象ID导致实例变量名称变为object_id
,其中包含短划线。 不允许破折号作为Ruby中标识符的一部分。因此错误。
您似乎在某处使用@content_for_details_view_builder__-626960428
的实例作为DetailsViewBuilder
的参数,是吗?或者它可能间接地发生在你正在使用的某个库中。
在任何情况下,如果这是正确的行为,并且您想要的只是避免实例变量名称错误,那么修复很简单。将content_for
更改为 object_id
,以确保实例变量永远不会包含短划线:
object_id.abs
答案 1 :(得分:0)
在您发布的链接中使用caller()
的建议实际上非常好。
文档有一个很好的例子,但你似乎错过了这一部分:
可选的start参数确定要从结果中省略的初始堆栈条目数。
基本上caller()
是你从未处理的异常中得到的堆栈跟踪的内容,只有你可以说它应该显示多少行。