Rails 7 way of auto-loading methods into controllers via engine

ghz 8months ago ⋅ 95 views

I'm looking into updating one of my favorite CMSs to Rails 7 that have been archived on github (PushType). Only I haven't coded Rails since Rails 6. Apparently, something about autoloading methods changed in Rails 7. I am getting this error:

NameError: uninitialized constant PushType::ApplicationControllerMethods
          include PushType::ApplicationControllerMethods
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

for this line in the engine:

      initializer 'push_type.application_controller' do
        ActiveSupport.on_load :action_controller do
          # ActionController::Base.send :include, PushType::ApplicationControllerMethods
          include PushType::ApplicationControllerMethods
        end
      end
  • the engine is located in root/core/lib/push_type/core/engine.rb
  • the location of the definition of the controller methods in question is at: root/core/app/controllers/concerns -- within concerns directory namespacing should work but it isn't, in the controller concerns directory the methods are found in push_type/application_controller_methods.rb

I don't know what I'm doing given my hiatus from the language. but in my attempt to resolve this I have tried autoloading that concerns directory within the gem's engine like this:

    config.autoload_paths << File.expand_path("../../../app/controllers/concerns", __FILE__) <<
                             # File.expand_path("../../../app/controllers/concerns/push_type", __FILE__)
                             File.expand_path("../../../app/helpers", __FILE__)

the full engine.rb file looks like this:

module PushType
  module Core
    class Engine < ::Rails::Engine
      isolate_namespace PushType
      engine_name 'push_type'

      config.autoload_paths << File.expand_path("../../../app/controllers/concerns", __FILE__) <<
                             # File.expand_path("../../../app/controllers/concerns/push_type", __FILE__)
                             File.expand_path("../../../app/helpers", __FILE__)

      # config.autoload_paths << "#{root}/app/controllers/concerns" <<
      #                         "#{root}/app/controllers/concerns/push_type" <<
      #                         "#{root}/app/helpers"

      # lib = root.join("lib")
      # config.autoload_once_paths.ignore(
      #   lib.join("assets"),
      #   lib.join("tasks"),
      #   lib.join("generators")
      # )

      config.generators do |g|
        g.assets false
        g.helper false
        g.test_framework  :test_unit, fixture: false
        g.hidden_namespaces << 'push_type:dummy' << 'push_type:field'
      end

      config.assets.precompile += %w(
        *.gif *.jpg *.png *.svg *.eot *.ttf *.woff *.woff2
      )

      config.to_prepare do
        Rails.application.eager_load! unless Rails.application.config.cache_classes
      end

      initializer 'push_type.dragonfly_config' do
        PushType.config.dragonfly_secret ||= Rails.application.secrets.secret_key_base
        PushType.dragonfly_app_setup!
      end

      initializer 'push_type.application_controller' do
        ActiveSupport.on_load :action_controller do
          # ActionController::Base.send :include, PushType::ApplicationControllerMethods
          include PushType::ApplicationControllerMethods
        end
      end

      initializer 'push_type.menu_helpers' do
        ActiveSupport.on_load :action_view do
          include PushType::MenuBuilder::Helpers
        end
      end
    end
  end
end

Answers

It seems like the issue might be related to how Rails 7 handles autoloading and namespace resolution. Let's try to troubleshoot and resolve the problem:

  1. Check File Naming: Ensure that the file containing the PushType::ApplicationControllerMethods module is named correctly according to Rails conventions. In Rails 7, autoloading is stricter, so file naming must match the module or class names.

  2. Namespace Resolution: Make sure that the module PushType::ApplicationControllerMethods is defined correctly within the file push_type/application_controller_methods.rb. Check if there are any syntax errors or namespace mismatches.

  3. Autoloading Configuration: Instead of manually adding autoload paths in the engine, rely on Rails' autoloading mechanisms. Ensure that the concerns directory is in the correct autoload path for Rails to automatically load the module.

    # Ensure that the concerns directory is autoloaded
    config.autoload_paths << "#{config.root}/app/controllers/concerns"
    
  4. Module Inclusion: Double-check that the module is included correctly within the engine's initializer. It seems like you're already doing this correctly, but make sure that the module is loaded and available at the time of inclusion.

    initializer 'push_type.application_controller' do
      ActiveSupport.on_load :action_controller do
        include PushType::ApplicationControllerMethods
      end
    end
    
  5. Namespace Resolution: If the PushType::ApplicationControllerMethods module is within the correct file and namespace, ensure that there are no conflicts with other autoloaded modules or classes. Rails 7 might have stricter namespace resolution rules.

  6. Restart the Server: After making changes, restart the Rails server to ensure that all autoload paths are loaded correctly and changes take effect.

By following these steps and ensuring correct file naming, namespace resolution, and autoload configuration, you should be able to resolve the NameError and include the PushType::ApplicationControllerMethods module successfully in your Rails 7 application.