Classes with the same name results in uninitialized constant when using Rails 6 Zeitwerk

408 Views Asked by At

I'm having issues with zeitwerk where I can't access another models constant that shares the same name. For example:

in /app/models I have a worker.rb file with a constant RETRY_COUNT

class Worker < ApplicationRecord
  RETRY_COUNT = 10
end

and in /lib I have a /critical/worker.rb file but namespaced under critical

module Critical
  class Worker
    some_method(::Worker::RETRY_COUNT)
  end
end

I'm able to call the worker model class using ::Worker, but when I call ::RETRY_COUNT, it results in

NameError: uninitialized constant Worker (call 'Worker.connection' to establish a connection)::RETRY_COUNT

Anyway around this? I could just hardcode the RETRY_COUNT on the Critical::Worker class but I'd like to avoid doing that.

1

There are 1 best solutions below

3
On

Based on your updates, I'm fairly certain you have a circular dependency. has_many calls are processed during "ApplicationRecord initialization". During "AR initialization", one of them references Critical::Worker.foo in a has_many, which references ::Worker (an AR) for RETRY_COUNT, which isn't done initializing yet.

If you need this value for "AR initialization time", then put it in a file that has no other dependencies.

module Independent # no other dependencies in this file
  RETRY_COUNT = 10
end

Then:

class Worker < ApplicationRecord
  RETRY_COUNT = Independent::RETRY_COUNT
end

module Critical
  class Worker
    RETRY_COUNT = Independent::RETRY_COUNT
  end
end

Zeitgeist should then be able to figure out it needs to load Independent before anything else, like your AR classes.