这种特定方法导致应用程序中断:
# 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
使用的建议可以caller()
用于从某种方法中找出堆栈跟踪.但是,我也会分享(我认为)解决问题的方法.
该to_s
方法返回一个字符串,用于动态设置实例变量.该DetailsViewBuilder
的 object_id
是变量名称的一部分.对象ID表示对象在内存中的位置.与直觉相反,object_id
对象的有时可能是负整数.是否发生这种情况也可能与平台有关.这解释了为什么您只在生产中看到此错误.负对象ID导致实例变量名称变为类似@content_for_details_view_builder__-626960428
,其中包含短划线.Ruby中不允许使用破折号作为标识符的一部分.因此错误.
看来你正在某个地方使用DetailsViewBuilder
as参数的实例content_for
,是吗?或者它可能间接地发生在您使用的某些库中.
在任何情况下,如果这是正确的行为,并且您想要的只是避免实例变量名称错误,那么修复很简单.更改object_id
为object_id.abs
保证实例变量永远不包含破折号:
def to_s "#{self.class.name.underscore}__#{object_id.abs}" end