Circular dependency detected while autoloading constant (Rails 4, Ruby 2)

dpyro picture dpyro · May 21, 2014 · Viewed 13.1k times · Source

configs/routes.rb Shutters and Paints are subresources of Jobs.

resources :jobs do
    resources :shutters
    resources :paints
end

app/models/job.rb A Job contains many Shutters and many Paints.

class Job < ActiveRecord::Base
    has_many :shutters, dependent: :delete_all
    has_many :paints, dependent: :delete_all

    accepts_nested_attributes_for :shutters, allow_destroy: true, :reject_if => lambda { |a| a[:no].blank? }
    accepts_nested_attributes_for :paints, allow_destroy: true, :reject_if => lambda { |a| a[:name].blank? }`

app/models/shutter.rb A Shutter contains belongs to one Job and one Paint.

class Shutter < ActiveRecord::Base
    belongs_to :job
    belongs_to :paint

app/models/paint.rb A Paint belongs to one Job but can be referenced by many Shutters in that job.

class Paint < ActiveRecord::Base
    belongs_to :job
    has_many :shutters

Both Jobs#show and Jobs#edit work fine with the code <%= debug @job.paints %> if there are no Paints already in the database. But the moment a paint is added, a RuntimeError is raised, "Circular dependency detected while autoloading constant PAINT".

What's the best way to fix this error?

Edit: Controller info

app/controllers/jobs_controller.rb

class JobsController < ApplicationController
    before_action :set_job, only: [:show, :edit, :update, :destroy]

    ...

    # GET /jobs/1
    # GET /jobs/1.json
    def show
    end

    # GET /jobs/new
    def new
        @job = Job.new
        @job.shutters.build
        @job.paints.build
    end

    # GET /jobs/1/edit
    def edit
        @job.shutters.build
        @job.paints.build
    end

app/controllers/shutters_controller.rb

class ShuttersController < ApplicationController
    def new
        @shutter = Shutter.new
    end

    def destroy
        @shutter = Shutter.find(params[:id])
        @job = Job.find(@shutter[:job_id])
        @shutter.destroy
        respond_to do |format|
            format.html {redirect_to @job, notice: 'Shutter was succesfully deleted.' }
        end
    end
end

app/controllers/paints_controller.rb

class PaintsController < ApplicationController
    def new
        @paint = Paint.new
    end

    def destroy
        @paint = Paint.find(params[:id])
        @job = Job.find(@paint[:job_id])
        @paint.destroy
        respond_to do |format|
            format.html {redirect_to @job, notice: 'Paint was succesfully deleted.' }
        end
    end
end

Answer

dpyro picture dpyro · May 26, 2014

The problem was none of these. It was actually that my Paint model contained a field named :type, which is a reserved keyword for meta-classing or something as such. Was thankfully helped by the kind folks at #RubyOnRails, else a newbie like me would have tried to start from scratch, run into the same problem, and would have never have figured this out. Hopefully this helps some future Googler. Pay it forward!