Troubleshooting LoadErrors in Rails tests

I am proposing a patch to help cope with the dreaded Rails LoadError:

  LoadError: Expected foo.rb to define Foo

In Ruby, it is simple to load code, just require it. In script/console:

  >> require 'account_controller'
  => ["AccountController"]

Rails extends this to magically find classes just based on their name:

  >> AccountController
  => AccountController

Most of the time, if a class does not exist, you get a helpful exception:

  >> AccountController
  MissingSourceFile: no such file to load -- hpricot_scan

Ah, so my AccountController depends on hpricot, which isn't available for some reason. Solution: go find hpricot.

But once in a while this problem presents a different symptom:

  >> AccountController
  LoadError: Expected account_controller.rb to define AccountController

This is confusing, since account_controller.rb does define AccountController! Experienced Rails developers know that this cryptic message actually means "Something went wrong in application_controller.rb, but Rails swallowed the real exception." After being bitten by this on three different projects in the last two weeks, I decided to track the issue down. Turns out the problem is in how fixtures get loaded:

  begin
    require_dependency file_name
  rescue LoadError
    # Let's hope the developer has included it himself
  end

After fixtures swallow the real MissingSourceFile for a subdependency such as hpricot, ActiveSupport raises a misleading LoadError for the original dependency (account_controller.rb) that references hpricot.

In a perfect world, I would simply have fixtures stop swallowing LoadErrors. But the comment strongly suggests that some code depends on this behavior. So weaker sauce is to at least log the problem:

  def try_to_load_dependency(file_name)
    require_dependency file_name
  rescue LoadError => e
    ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
  end

If anybody knows how to distinguish the confusing LoadErrors from the expected ones, please go and improve the patch.

Get In Touch