在Rails中使用gem时,“无法删除Object :: ClassMethods”的内容源于什么?

在安装提供类似问题的gem时,我经常遇到问题:

有谁知道这源于什么? 我已经看过几个不同的案例,但仍然没有学到究竟是什么导致它。

$ sudo rake gems:install --trace (in /u/app/releases/20100213003957) ** Invoke gems:install (first_time) ** Invoke gems:base (first_time) ** Execute gems:base ** Invoke environment (first_time) ** Execute environment rake aborted! cannot remove Object::ClassMethods /u/app/releases/20100213003957/vendor/rails/activesupport/lib/active_support/dependencies.rb:603:in `remove_const' /u/app/releases/20100213003957/vendor/rails/activesupport/lib/active_support/dependencies.rb:603:in `remove_constant' /u/app/releases/20100213003957/vendor/rails/activesupport/lib/active_support/dependencies.rb:603:in `instance_eval' /u/app/releases/20100213003957/vendor/rails/activesupport/lib/active_support/dependencies.rb:603:in `remove_constant' /u/app/releases/20100213003957/vendor/rails/activesupport/lib/active_support/dependencies.rb:549:in `new_constants_in' /u/app/releases/20100213003957/vendor/rails/activesupport/lib/active_support/dependencies.rb:549:in `each' /u/app/releases/20100213003957/vendor/rails/activesupport/lib/active_support/dependencies.rb:549:in `new_constants_in' /u/app/releases/20100213003957/vendor/rails/activesupport/lib/active_support/dependencies.rb:156:in `require' /u/app/releases/20100213003957/vendor/rails/railties/lib/tasks/misc.rake:4 /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:617:in `call' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:617:in `execute' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:612:in `each' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:612:in `execute' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:578:in `invoke_with_call_chain' /usr/lib64/ruby/1.8/monitor.rb:242:in `synchronize' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:571:in `invoke_with_call_chain' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:564:in `invoke' /u/app/releases/20100213003957/vendor/rails/railties/lib/tasks/gems.rake:17 /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:617:in `call' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:617:in `execute' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:612:in `each' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:612:in `execute' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:578:in `invoke_with_call_chain' /usr/lib64/ruby/1.8/monitor.rb:242:in `synchronize' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:571:in `invoke_with_call_chain' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:588:in `invoke_prerequisites' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:585:in `each' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:585:in `invoke_prerequisites' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:577:in `invoke_with_call_chain' /usr/lib64/ruby/1.8/monitor.rb:242:in `synchronize' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:571:in `invoke_with_call_chain' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:564:in `invoke' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:2027:in `invoke_task' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:2005:in `top_level' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:2005:in `each' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:2005:in `top_level' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:2044:in `standard_exception_handling' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:1999:in `top_level' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:1977:in `run' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:2044:in `standard_exception_handling' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/lib/rake.rb:1974:in `run' /usr/lib64/ruby/gems/1.8/gems/rake-0.8.4/bin/rake:31 /usr/bin/rake:19:in `load' /usr/bin/rake:19 

此错误的原因是双重例外。 通常代码中的某些内容会崩溃,从而引发初始exception。 然后Rails的自定义需要尝试通过删除部分定义的常量来保持命名空间的清洁,这是new_constants_in方法的目的。 问题是new_constants_in没有正确处理代码中某处的某些特定构造,我怀疑是由于error handling模块名称空间或其他东西(因为ClassMethods可能在Object之外的某些模块中)。 在任何情况下,我都没有将错误追溯到Rails组件或其他任何东西,因为坦率地说它不值得努力。

解决方案(没有提出对Rails核心有点侵略性的东西)是一个快速的黑客,以找出引起原始exception的原因。 您需要做的就是去调用Dependencies.new_constants_in并将其注释掉(有几个地方可以这样)。 例如:

 def require(file, *extras) #:nodoc: if Dependencies.load? Dependencies.new_constants_in(Object) { super } else super end rescue Exception => exception # errors from required file exception.blame_file! file raise end 

注释掉new_constants_in东西:

 def require(file, *extras) #:nodoc: # if Dependencies.load? # Dependencies.new_constants_in(Object) { super } # else super # end #rescue Exception => exception # errors from required file # exception.blame_file! file # raise end 

然后你会马上看到你的错误。

我相信我找到了一种实用的非侵入式方法来解决问题的根源。 它适用于我(Rails 2.3):

碰巧发生exception#blame_file! 尽管它会失败并导致新的错误,因此会在某个时刻调用,从而屏蔽原始错误。

所以,打开你的FIRST初始化程序并添加,

 class Exception def blame_file!( file ) puts "CULPRIT >> '#{file.to_s}' # #{self.to_s}" end end 

您将获得被控制的文件和原始错误消息。 这应该足以找出你的问题。

不要忘记删除Exception初始化程序代码段。

我刚刚再遇到这个问题。 经过一些调试后,我得出了这样的结论:这个奇怪的错误意味着Rails在需要某些特定库时遇到了一些麻烦。 问题是Rails没有告诉我们哪个库导致了问题。 所以,你要做的第一步是:

打开此文件(或安装中的相应文件):/ u/app/releases/20100213003957/vendor/rails/activesupport/lib/active_support/dependencies.rb

并编辑load_with_new_constant_marking方法,使其如下所示:

 def load_with_new_constant_marking(file, *extras) #:nodoc: if Dependencies.load? Dependencies.new_constants_in(Object) { load_without_new_constant_marking(file, *extras) } else load_without_new_constant_marking(file, *extras) end rescue Exception => exception # errors from loading file puts "FAILS HERE: " + file exception.blame_file! file raise end 

从现在开始,当运行您的应用程序或rake任务时,Rails不会告诉您“无法删除Object :: ClassMethods”,而是会告诉您哪个文件导致了问题(只需查看“FAILS HERE”语句)。 (顺便说一句。我想这就是exception.blame_file!方法应该做的事情,但显然不会这样。)

找到导致问题的文件后,您可以深入了解该特定块并使用一些exception块来解决问题的核心。

希望这可以帮助。

我今天也开始捕捉这个奇怪的错误 – 追溯到一个过时的mysql gem。

我刚刚使用Mac MySQL软件包(PrefPane附带的软件包)转换为Homebrew编译版本,旧的/ usr / local / mysql在我的PATH中挥之不去

删除该目录(以及旧MySQL的其他痕迹),然后重新捆绑我的应用程序解决了它!

我遇到了这个问题,尝试了上述各种解决方案,但无济于事。

在我的情况下,问题是我不小心在文件的顶部包含了ActionView::Helpers::TextHelperActionView::Helpers::NumberHelper (从而将它们包含在根Object类中),这在Rails 3.0中运行正常.0.rc,但在Rails 3.0.1中引发了“无法删除Object :: ClassMethods”,一旦引发,应用程序一直停留,直到服务器重新启动。

这开始发生在我身上,但只有在我的包中包含了delayed_job gem之后。 像上面的Eric一样,我在控制器的顶部包含了ActionView :: Helpers :: TextHelper和ActionView :: Helpers :: NumberHelper,但有趣的是,在我开始使用delayed_job之前,我没有任何问题。 我不知道发生了什么,我刚刚删除了包含,问题似乎已经消失了。