Circular dependency in Rails

Posted by Anton Katunin on 9 November 2014
Tags: code, rails

This is an interesing bug I've encountered this week. While our Rails application was working in development it was completely broken in UAT environment (which is 99% production like)

We were getting Circular dependency detected while autoloading constant error on all of our reports.

Not so long ago we've extracted group of controllers in its own rails engine with isolated namespace Merchant. After some investigation we've spotted the bug, let's see if you can find it.

module Merchant
  class Reports::PostsController < ApplicationController
  # some code here
  end
end

Do you see it? It's not obvious is it? How about these alternatives:

module Merchant
  module Reports
    class PostsController < ApplicationController
    # some code here
    end
  end
end
module Merchant::Reports
  class PostsController < Merchant::ApplicationController
  # some code here
  end
end
class Merchant::Reports::PostsController < Merchant::ApplicationController
  # some code here
end

All of these work except the first one. What's going on here? My guess will be

  1. Rails loads Merchant::Reports::PostsController controller
  2. It looks for Merchant::ApplicationController and loads it
  3. Merchant::ApplicationController somehow triggers the load of Merchant module, which loads all classes in it.
  4. repeat
  5. Show Circular dependency detected while autoloading constant error

So the fix was to rewrite it with different ruby style.


Read next:

Multiple logins at once with Browser Profiles