我認爲這種影響來自ActionController::Reloader
寫入的方式。下面是從ActionController::Reloader#call
2.3.3,請注意評論:
def call(env)
Dispatcher.reload_application
status, headers, body = @app.call(env)
# We do not want to call 'cleanup_application' in an ensure block
# because the returned Rack response body may lazily generate its data. This
# is for example the case if one calls
#
# render :text => lambda { ... code here which refers to application models ... }
#
# in an ActionController.
#
# Instead, we will want to cleanup the application code after the request is
# completely finished. So we wrap the body in a BodyWrapper class so that
# when the Rack handler calls #close during the end of the request, we get to
# run our cleanup code.
[status, headers, BodyWrapper.new(body)]
end
Dispatcher.reload_application
不會刪除自動加載的常量,Dispatcher.cleanup_application
一樣。 BodyWrapper#close
與可能出現的異常寫在心中:
def close
@body.close if @body.respond_to?(:close)
ensure
Dispatcher.cleanup_application
end
然而,這並沒有幫助,因爲如果@app.call
在ActionController::Reloader#call
拋出一個異常,BodyWrapper
不會被實例化,Dispatcher.cleanup_application
不會被調用。
試想以下情形:
- 我使我的文件一個影響API調用
- 我打API調用,看看錯誤,在這一點上,包括一個有缺陷的所有文件的變化AREN 「T卸載
- 我做一個codefix和命中相同 API調用來檢查它是否工作
- 呼叫會像以前一樣擊潰了同樣的方式,以老班/對象/模塊。這會拋出相同的錯誤並再次在內存中留下加載的常量
傳統控制器引發錯誤時不會發生這種情況,因爲這些錯誤由ActionController::Rescue
處理。這種例外情況未達到ActionController::Reloader
。
簡單的解決辦法是把後備救援條款列入API路由中間件,這樣一些變化:
def call(env)
# route API call
resuce Exception
Dispatcher.cleanup_application
raise
end
注意,這就是我的回答對3歲的問題,我也跟着2.3.3調用堆棧。較新版本的rails可能會有不同的處理方式。
我也有這個問題。 – 2011-04-14 18:52:26