0

管理フレームワーク用のプラグインを開発していますが、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) 

おそらく重要なことですが、本番モードではプラグインは安定しており、アクション(showを含む)を正しくルーティングします。

4

2 に答える 2

1

Projectこれは通常、レールリローダーを考慮せずにプラグインからコアモデル(おそらくモデル)にパッチを適用することによって発生します。

メソッドをオーバーライドし(たとえば、を使用してalias_method_chain)、パッチが2回ロードされると、古いメソッドを呼び出すときに無限ループを簡単に作成できます。

# 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

foofoo_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が発生します。これは、パッチの2回目のロード後、最初のパッチのメソッドをfoo_without_feature参照するためです。foo_with_featureそれを呼び出すときfoo_without_feature、スタックがいっぱいになるまで何度も何度も呼び出します。

2番目のリクエストでのみクラッシュするとおっしゃいました。これは、クラスリローダーで何かがおかしい場合の典型的な動作です。デフォルトでは、Railsは開発モードではすべてのリクエストですべてのクラスをリロードしますが、本番モードでは1回だけリロードします。

レールリローダーを使いこなすのは少し難しい場合があります。いくつかの一般的なガイドラインとして、

  1. パッチをロードするときrequire_dependencyに代わりに使用するrequire
  2. を使用してパッチをロードしますDispatcher.to_prepare
  3. パッチを適用したクラスを常に宣言するunloadable

最も重要な部分はを使用することDispatcher.to_prepareです。これは、本番モードで1回呼び出され、開発モードで各要求の前に呼び出されるコールバックであるため、パッチをロードするための理想的な場所です。

ただし、補足として、Redmine 2(または今後のChiliProject 4)、つまりRails 3を使用する場合、クラスのパッチ適用はこのアプローチとはかなり異なり、おそらく簡単です。

于 2012-07-02T14:46:57.637 に答える
0

「スタックレベルが深すぎます」というエラーは、スタックオーバーフローが発生していることを意味します(サイトに名前が付けられるのに十分な頻度で発生します)。これは、関数がそれ自体を無期限に呼び出す場合、または2つの関数が互いに無期限に呼び出す場合に発生します。

エラーは5行目で発生するため、ソースを確認しlink_to_if_authorizedます。そこに何かがあり、無限ループを引き起こしています。

于 2012-07-01T18:06:31.763 に答える