Search code examples
ruby-on-railszeitwerk

Error calling a services class method in Rails 7.1


Rails 7.1

In my app/services/tools, I have a file: services_tools.rb

Inside services_tools.rb, I have:

module ServicesTools
  class ErbToSlim
    def convert_erb_to_slim(erb_file)
      ...........
    end
  end

  class NestedMigrationCreator
    def generate_nested_migration(migration_namespace:, migration_name:, migration_code: nil)
      ..........
    end
  end
end

I go to the command line, and do:

rails c

and then I do:

creator = ServicesTools::NestedMigrationCreator.new

I'm getting the following message:

(irb):1:in `<main>': uninitialized constant ServicesTools (NameError)

In the console, when I do:

ActiveSupport::Dependencies.autoload_paths

I get:

"/lib",
"/test/mailers/previews",
"/app/channels",
"/app/controllers",
"/app/controllers/concerns",
"/app/helpers",
"/app/jobs",
"/app/mailers",
"/app/models",
"/app/models/concerns",
"/app/services",
...

Any ideas?


Solution

  • Your app/services is a root directory, which means files relative to that directory must correspond to module/class names to be autoloadable:

    # app/services/tools/services_tools.rb
    #              '^^^' '^^^^^^^^^^^^'
    #                |         |  
    module Tools # --'         |
      module ServicesTools # --'
      end
    end
    

    Which seems a bit awkward. This could be better:

    # app/services/tools/erb_to_slim.rb
    module Tools
      class ErbToSlim
      end
    end
    
    # app/services/tools/nested_migration_creator.rb
    module Tools
      class NestedMigrationCreator
      end
    end
    

    In general, it is best to define one constant per file. However, this also works, as long as file name corresponds to a class/module name you can do whatever inside:

    # app/services/tools.rb
    
    module Tools
      class ErbToSlim
      end
    
      class NestedMigrationCreator
      end
    end
    

    https://github.com/fxn/zeitwerk#file-structure