【问题标题】:stack level to deep Rails 2.3.14堆栈级别到深 Rails 2.3.14
【发布时间】:2012-07-01 15:28:11
【问题描述】:

我正在为管理框架开发一个插件,当我在开发模式下启动 webrick 服务器时,出现了一个奇怪的错误(堆栈级别太深)。当一个动作(例如show 动作)开始渲染一个模板时,就会发生这种情况。不幸的是,我不知道为什么会这样。

SystemStackError in Stories#show

Showing vendor/plugins/stories/app/views/stories/show.rhtml where line #5 raised:

stack level too deep

Extracted source (around line #5):

    5: link_to_if_authorized 'aa', {:controller => "stories", :action => "index", :id => @story.id, :project_id => @story.project.id}, :title => l(:view_story), :class => 'icon icon-zoom-out'
    6: link_to_if_authorized 'bb', {:controller => "stories", :action => "edit", :id => @story.id, :project_id => @story.project.id}, :title => l(:button_edit), :class => 'icon icon-edit'
    7: link_to 'bb', {:id => @story.id, :project_id => @story.project.id}, :confirm => 'Really  delete?', :method => :delete, :class => 'icon icon-del' if User.current.allowed_to? (:delete_stories, @project)

    RAILS_ROOT: /home/haendwic/Documents/Aptana Studio 3 Workspace/1.4-stable-SVN
    Application Trace | Framework Trace | Full Trace

    /var/lib/gems/1.8/gems/activerecord-2.3.14/lib/active_record/attribute_methods.rb:248:in method_missing'
    /var/lib/gems/1.8/gems/activerecord-2.3.14/lib/active_record/attribute_methods.rb:249:in method_missing'
     /var/lib/gems/1.8/gems/activerecord-2.3.14/lib/active_record/associations /association_proxy.rb:215:in send'
     /var/lib/gems/1.8/gems/activerecord-2.3.14/lib/active_record/associations/association_proxy.rb:215:in method_missing'
     /home/haendwic/Documents/Aptana Studio 3 Workspace/1.4-stable-SVN/vendor/plugins/stories/app/views/stories/show.rhtml:5:in  _run_rhtml_vendor47plugins47stories47app47views47stories47show46rhtml'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_view/renderable.rb:34:in send'
      /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_view/renderable.rb:34:in render'
      /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_view/base.rb:306:in with_template'
      /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_view/renderable.rb:30:in render'
      /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_view/template.rb:205:in render_template'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_view/base.rb:265:in render'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_view/base.rb:348:in _render_with_layout'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_view/base.rb:262:in render'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/base.rb:1252:in render_for_file'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/base.rb:936:in render_without_benchmark'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/benchmarking.rb:51:in render'
    /var/lib/gems/1.8/gems/activesupport-2.3.14/lib/active_support/core_ext/benchmark.rb:17:in ms'
    /usr/lib/ruby/1.8/benchmark.rb:308:in realtime'
    /var/lib/gems/1.8/gems/activesupport-2.3.14/lib/active_support/core_ext/benchmark.rb:17:in ms'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/benchmarking.rb:51:in render'
/home/haendwic/Documents/Aptana Studio 3 Workspace/1.4-stable-SVN/vendor/plugins/stories/app/controllers/stories_controller.rb:104:in show'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/mime_responds.rb:135:in call'
      /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/mime_responds.rb:135:in custom'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/mime_responds.rb:179:in call'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/mime_responds.rb:179:in respond'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/mime_responds.rb:173:in each'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/mime_responds.rb:173:in respond'
      /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/mime_responds.rb:107:in respond_to'
    /home/haendwic/Documents/Aptana Studio 3 Workspace/1.4-stable-SVN/vendor/plugins/stories/app/controllers/stories_controller.rb:102:in show'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/base.rb:1333:in send'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/base.rb:1333:in perform_action_without_filters'
/var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/filters.rb:617:in call_filters'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/filters.rb:610:in perform_action_without_benchmark'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/benchmarking.rb:68:in perform_action_without_rescue'
     /var/lib/gems/1.8/gems/activesupport-2.3.14/lib/active_support/core_ext/benchmark.rb:17:in ms'
     /usr/lib/ruby/1.8/benchmark.rb:308:in realtime'
     /var/lib/gems/1.8/gems/activesupport-2.3.14/lib/active_support/core_ext/benchmark.rb:17:in ms'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/benchmarking.rb:68:in perform_action_without_rescue'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/rescue.rb:160:in perform_action_without_flash'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/flash.rb:151:in perform_action'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/base.rb:532:in send'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/base.rb:532:in process_without_filters'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/filters.rb:606:in process'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/base.rb:391:in process'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/base.rb:386:in call'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/routing/route_set.rb:438:in call'
     /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/dispatcher.rb:87:in dispatch'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/dispatcher.rb:121:in _call'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/dispatcher.rb:130:in build_middleware_stack'
    /var/lib/gems/1.8/gems/activerecord-2.3.14/lib/active_record/query_cache.rb:29:in call'
    /var/lib/gems/1.8/gems/activerecord-2.3.14/lib/active_record/query_cache.rb:29:in call'
    /var/lib/gems/1.8/gems/activerecord-2.3.14/lib/active_record/connection_adapters/abstract/query_cache.rb:34:in cache'
     /var/lib/gems/1.8/gems/activerecord-2.3.14/lib/active_record/query_cache.rb:9:in cache'
     /var/lib/gems/1.8/gems/activerecord-2.3.14/lib/active_record/query_cache.rb:28:in call'
     /var/lib/gems/1.8/gems/activerecord-2.3.14/lib/active_record/connection_adapters/abstract/connection_pool.rb:361:in call'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/string_coercion.rb:25:in call'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/head.rb:9:in call'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/methodoverride.rb:24:in call'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/params_parser.rb:15:in call'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/session /cookie_store.rb:99:in call'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/failsafe.rb:26:in call'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/lock.rb:11:in call'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/lock.rb:11:in synchronize'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/lock.rb:11:in call'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/dispatcher.rb:114:in call'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/reloader.rb:34:in run'
    /var/lib/gems/1.8/gems/actionpack-2.3.14/lib/action_controller/dispatcher.rb:108:in call'
    /var/lib/gems/1.8/gems/rails-2.3.14/lib/rails/rack/static.rb:31:in call'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/urlmap.rb:47:in call'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/urlmap.rb:41:in each'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/urlmap.rb:41:in call'
    /var/lib/gems/1.8/gems/rails-2.3.14/lib/rails/rack/log_tailer.rb:17:in call'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/content_length.rb:13:in call'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/handler/webrick.rb:48:in service'
    /usr/lib/ruby/1.8/webrick/httpserver.rb:104:in service'
    /usr/lib/ruby/1.8/webrick/httpserver.rb:65:in run'
    /usr/lib/ruby/1.8/webrick/server.rb:173:in start_thread'
    /usr/lib/ruby/1.8/webrick/server.rb:162:in start'
    /usr/lib/ruby/1.8/webrick/server.rb:162:in start_thread'
    /usr/lib/ruby/1.8/webrick/server.rb:95:in start'
    /usr/lib/ruby/1.8/webrick/server.rb:92:in each'
    /usr/lib/ruby/1.8/webrick/server.rb:92:in start'
    /usr/lib/ruby/1.8/webrick/server.rb:23:in start'
    /usr/lib/ruby/1.8/webrick/server.rb:82:in start'
    /var/lib/gems/1.8/gems/rack-1.1.3/lib/rack/handler/webrick.rb:14:in run'
    /var/lib/gems/1.8/gems/rails-2.3.14/lib/commands/server.rb:111
    script/server:3:in require'
    script/server:3
Request

Parameters:

{"project_id"=>"1",
 "id"=>"2"}

Show session dump
Response

Headers:

{"Cache-Control"=>"no-cache",
 "Content-Type"=>"text/html"}

这是来自控制器的操作

def show 
 @edit_allowed = User.current.allowed_to?(:edit_stories, @project)
 respond_to do |format|
  format.html {
    render :template => 'stories/show'
  }
  format.api
  format.pdf  { send_data(story_to_pdf(@story), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@story.id}.pdf") }
 end                                
end

最后是视图的一部分

     link_to_if_authorized 'aa', {:controller => "stories", :action => "index", :id => @story.id, :project_id => @story.project.id}, :title => l(:view_story), :class => 'icon icon-zoom-out'
     link_to_if_authorized 'bb', {:controller => "stories", :action => "edit", :id => @story.id, :project_id => @story.project.id}, :title => l(:button_edit), :class => 'icon icon-edit' 
    link_to 'bb', {:id => @story.id, :project_id => @story.project.id}, :confirm => 'Really delete?', :method => :delete, :class => 'icon icon-del' if User.current.allowed_to?(:delete_stories, @project) 

也许重要的是要说,在生产模式下,插件是稳定的并且可以正确路由动作(包括显示)

【问题讨论】:

  • 你能把link_to_if_authorized的代码贴出来吗?
  • 生产和开发中是否有相同版本的 ruby​​?
  • def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller ], options[:action]) 结束

标签: ruby-on-rails redmine redmine-plugins


【解决方案1】:

这通常是由于您(或其他人)从插件中修补核心模型(可能是 Project 模型)而没有考虑到 rails reloader。

如果你重写方法(例如使用alias_method_chain)并且你的补丁被加载了两次,你可以很容易地在调用旧方法时创建一个无限循环。

# This is our initial class
class MyClass
  def foo
    puts "original foo"
  end
end

module Patch
  def self.included(base)
    base.alias_method_chain :foo, :feature
  end

  def foo_with_feature
    foo_without_feature # call the "original" method
    puts "foo with feature"
  end
end

# patch the class
MyClass.send(:include, Patch)

# Now call the patched method
MyClass.new.foo
# prints:
#   original foo
#   foo with feature

foo 现在指的是方法foo_with_feature 而原来的foo 方法现在可以从foo_without_feature 访问

好的,到目前为止一切看起来都很好。现在让我们看看如果我们再次加载补丁会发生什么

# patch again
MyClass.send(:include, Patch)

# And call the method again
MyClass.new.foo
# SystemStackError: stack level too deep
#   from (irb):7:in `foo_without_feature'
#   from (irb):7:in `foo'
#   from (irb):27

您会看到由无限循环导致的 SystemStackError。这是因为在第二次加载补丁后,foo_without_feature 现在引用了第一个补丁中的foo_with_feature 方法。调用的时候会一遍遍地调用foo_without_feature,直到栈满。

你说它只在第二个请求时崩溃。当类重新加载器出现异常时,这正是典型的行为。默认情况下,Rails 会在开发模式下的每个请求上重新加载所有类,但在生产模式下只会重新加载一次。

有时驯服 rails reloader 有点棘手。作为一些一般准则,您应该

  1. 加载补丁时使用require_dependency 而不是require
  2. 使用Dispatcher.to_prepare 加载您的补丁
  3. 总是声明修补的类unloadable

最关键的部分是使用Dispatcher.to_prepare。它是一个回调,在生产模式和开发模式的每个请求之前调用一次,因此是加载补丁的理想位置。

不过附带说明:当使用 Redmine 2(或即将推出的 ChiliProject 4),即 Rails 3 时,类修补将与这种方法有很大不同 - 很可能更容易。

【讨论】:

  • 谢谢伙计,它似乎工作。我需要向 2 个控制器添加一些 require_dependences,并且错误似乎已修复..
【解决方案2】:

“堆栈级别太深”错误意味着您有堆栈溢出(它经常发生以至于有一个以它命名的站点)。当一个函数无限期地调用自身或两个函数无限期地相互调用时,就会发生这种情况。

您的错误发生在第 5 行,所以我会检查 link_to_if_authorized 的来源。里面的东西导致了无限循环。

【讨论】:

  • def link_to(name, options={}) url = { :format => name.to_s.downcase }.merge(options.delete(:url) || {}).except(' page') 标题 = options.delete(:caption) || name html_options = { :class=> name.to_s.downcase, :rel => 'nofollow' }.merge(options) @view.content_tag('span', @view.link_to(caption, url, html_options)) end
  • def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference) link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller ], 选项[:action])
  • 当我注释掉这两种方法(link_to、link_to_if_authorized)时,会出现同样的错误,所以问题必须更早开始(?)
  • 如果我重新启动服务器,第一个请求工作正常。在此之后,堆栈级别的恐怖开始了..
猜你喜欢
  • 2012-07-24
  • 1970-01-01
  • 2017-08-19
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2021-01-01
相关资源
最近更新 更多