views:

441

answers:

5

Frequently I have run into a problem when installing gems that provides a problem like:

Does anyone know what this stems from? I've seen in it several different cases, yet still haven't learned what exactly is causing it.

$ 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
A: 

I also started catching this bizarre error today -- traced it back to an out-of-date mysql gem .

I'd just switched from using the Mac MySQL package (the one that comes with a PrefPane) to a Homebrew-compiled version and the old /usr/local/mysql was lingering in my PATH

Deleting that directory (and other traces of the old MySQL) and then re-bundling my app solved it!

jamiew
A: 

Hey guys!

I just came across this problem again. After some debugging I came to this conclusion: this weird error means that Rails has some troubles with requiring some particular library. The problem is that Rails doesn't tell us which library causes the problem. So, the first step you have to do is this:

Open this file (or the appropriate file in your installation): /u/app/releases/20100213003957/vendor/rails/activesupport/lib/active_support/dependencies.rb

and edit the load_with_new_constant_marking method so it looks like this:

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

From now on, when running your application or a rake task, instead of just telling you that it "cannot remove Object::ClassMethods" Rails will tell you which file causes the problem (just look for the "FAILS HERE" statement). (Btw. I suppose this is what the exception.blame_file! method should be doing, but it obviously doesn't work that way.)

After you have located the file which causes the problem, you can dig into that particular chunk and use some exception blocks to get to the core of the problem.

Hope this helps.

Milan Novota
A: 

Bluh. This problem mysteriously appeared for me (in Rails 3.0.0.beta4) after I ran rails plugin install 'git://github.com/rails/dynamic_form.git' But I can't figure out if that is actually the cause because it doesn't make any sense to me. I opened up dependencies.rb and did what Milan said (slightly different in Rails 3, in the load_dependency method):

  def load_dependency(file)
    if Dependencies.load?
      Dependencies.new_constants_in(Object) { yield }.presence
    else
      yield
    end
  rescue Exception => exception  # errors from loading file
    puts "FAILS HERE: " + file
    exception.blame_file! file
    raise
  end

and was greeted with this present:

$ rails server
FAILS HERE: json
FAILS HERE: Win32API
FAILS HERE: engine/parser
FAILS HERE: sqlite3/1.8/sqlite3_native
FAILS HERE: mongrel
=> Booting WEBrick
=> Rails 3.0.0.beta4 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
FAILS HERE: fast_xs
FAILS HERE: nested_multimap
FAILS HERE: nested_multimap_ext
FAILS HERE: regin

How exciting! Reinstalling any of the above that are gems doesn't fix it.

+2  A: 

The cause of this error is a double exception. Usually something in your code is crashing, which raises an initial exception. Then Rails' custom require attempts to keep the namespace clean by removing partially defined constants, which is the purpose of the new_constants_in method. The problem is that new_constants_in is not properly handling some particular construction somewhere within the code, I suspect due to mishandling of module namespaces or something (because ClassMethods is probably inside some module other than Object). In any case, I have not traced the error back to a Rails component or anything else, because frankly it's not worth the effort.

The solution (short of proposing something a little less invasive to Rails core) is a quick hack to figure out what raised the original exception. All you need to do is go to where Dependencies.new_constants_in is called and comment it out (there are a few places where this could be). So for example:

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

Comment out the new_constants_in stuff:

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

Then you'll see your error straight away.

dasil003