Search code examples
ruby-on-rails-7zeitwerk

Error loading .rb file in /lib after migration from rails 3 to rails 7


I have a very old application written with rails 3 and need to update it to current rails 7. I am stuck with a strange problem: in lib/assets there is a file tools.rb full of functions used across all models. First I had to move tools.rb from "lib/assets" into "lib"

require "matrix"

def first_function(t,p1,p2)
  <snip>...</snip>
end

...

def last_function(t,p1,p2)
  <snip>...</snip>
end

Now, invoking any of these functions results in the following error:

expected file /home/daniele/src/sp4ct/lib/tools.rb to define constant Tools, but didn't

Then if I reload the same page a second time the error does not occurr anymore... No idea of what is happening


Solution

  • There are several things to fix in here.

    First, the file is in the autoload paths but it is not autoloadable because it does not follow the conventions (it does not define Assets::Tools).

    This configuration

    config.autoload_paths += Dir["#{config.root}/lib/**/
    

    is not correct, autoload paths represent root namespaces, so Rails puts app/controllers in the autoload paths, but you don't put app/controllers/admin in the autoload paths because that is a subdirectory that represents the Admin namespace.

    Please delete that line.

    Rails 7.1 defines autoload_lib, which is more convenient, but in Rails 7.0 you can still do the following in its place:

    lib = "#{root}/lib"
    config.eager_load_paths << lib
    
    # Ignore directories that do contain autoloadable .rb files.
    Rails.autoloaders.main.ignore(
      "#{lib}/assets",
      "#{lib}/tasks",
      "#{lib}/tools.rb" # you can restore the file in its original place
    )
    

    Then, in your models require "tools" as the application did before.