ruby - 如何找到运行时调用 Ruby 方法的位置?

标签 ruby methods callstack inspect

此特定方法导致应用程序中断:

# 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

我 100% 确定是 to_s 方法导致了错误。我不确定它在哪里被调用,但它导致了这个错误。注意上面它产生了构建器变量。该构建器变量包含具有此方法的类。我需要找到一种更好的方法来检查元素,这样我就可以透明地看到调用堆栈,并且给定一个方法,我知道它在哪里被调用。奇怪的是,此方法在我的本地计算机上有效,但在服务器上的生产中导致错误。这是回溯的一些花絮:

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 方法返回一个用于动态设置实例变量的字符串。 DetailsViewBuilderobject_id 是变量名称的一部分。对象 ID 表示对象在内存中的位置。与直觉相反,对象的 object_id 有时可能是负整数。这种情况是否发生也可能取决于平台。这解释了为什么您只在生产中看到此错误。负对象 ID 会导致实例变量名称变为类似于 @content_for_details_view_builder__-626960428 的名称,其中包含破折号。 破折号不允许作为 Ruby 中标识符的一部分。因此出现错误。

您似乎在某处使用 DetailsViewBuilder 的实例作为 content_for 的参数,对吗?或者它可能会在您正在使用的某些库中间接发生。

无论如何,如果这是正确的行为,并且您想要的只是避免实例变量名称错误,那么修复很简单。将 object_id 更改为 object_id.abs 以保证实例变量从不包含破折号:

def to_s
  "#{self.class.name.underscore}__#{object_id.abs}"
end 

关于ruby - 如何找到运行时调用 Ruby 方法的位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5892247/

相关文章:

Javascript OOP,一个不会运行的简单计算器

c# - "A <T>(IList<T> x) where T : I"和 "A(IList<I> x)"之间的区别?

具有内部 Clear() 方法的 C# 结构

ruby - 有没有办法知道调用方法?

ruby-on-rails - 带有内联附件的 Rails 邮件程序错误

ruby-on-rails - Rails 4,在 Postgresql 中保存数组

ruby-on-rails - 通过银行转账处理 Rails 付款

ruby - Ruby 中的无方法错误

assembly - 汇编中的堆栈/基指针

java - 是否可以将方法名称存储在数组中,并计算它被调用的次数?