Railtie Initializer not running in plugin
Asked Answered
D

1

5

I recently switched from the gem version of resources_controller to a plugin as the gem version relied on git.

Inside the vendor/plugins/plugin/lib/plugin.rb file, the Railtie is as follows:

module Ardes
  module ResourcesController
    class Railtie < Rails::Railtie
      initializer 'ardes.resources_controller' do
        ActiveSupport.on_load(:action_controller) do
          extend Ardes::ResourcesController
          include Ardes::ResourcesController::RequestPathIntrospection
        end

        ActiveSupport.on_load(:active_record) do
          include Ardes::ActiveRecord::Saved
        end
      end
    end
  end
end

I've added a require 'resources_controller' in one of my initializers and it's properly loading this file. The problem is that although the Railtie is evaluated (a puts in the class block will hit), it never seems to actually call the initializer block itself. This is important of course as this is where it extends ActionController to include the resources_controller_for method.

This question is appears to have come up here and here. Though in both cases they found other ways around the problem and no direct answer was given for why the block wasn't being called.

From what I can tell in the Rails docs you can name your initializer block anything you'd like and it should run. I don't think it matters, but I first noticed the problem when running in production rails s -e production though I believe the same problem exists in development mode.

What may be going on?

For reference, full plugin is here: https://github.com/ianwhite/resources_controller

Declarer answered 14/9, 2011 at 20:50 Comment(0)
D
7

The problem you're having here is that you can't add new initializers once the initializer process has started.

Here, you're requiring the code that registers the initializers during the initializer process. When you use gems in the Gemfile, the initializers are registered in this code:

if defined?(Bundler)
  # If you precompile assets before deploying to production, use this line
  Bundler.require(*Rails.groups(:assets => %w(development test)))
  # If you want your assets lazily compiled in production, use this line
  # Bundler.require(:default, :assets, Rails.env)
end

This code executes before the initializers begin. In contrast, you are requiring the resources_controller code in an initializer file, which runs during the initialization process. As a result, it's too late to register new initializers.

What complicates the situation is that the load paths inside vendor/plugins are also set up during the initialization process, so you won't be able to require resources_controller in application.rb.

The easiest solution to your problem would be to use the :path feature in bundler. After installing the plugin, add this line to your Gemfile:

gem 'resources_controller', :path => "vendor/plugins/resources_controller"

You can then remove the require line from your initializer, and bundler will recognize that the plugin is a locally checked out gem and do what it would do if you used git.

Demerit answered 10/12, 2011 at 6:13 Comment(1)
Thanks for the answer. I ended up doing this in the end but forgot to come back and post a reply. Thanks for the descriptive answer as it was useful to learn more about the initialization process.Declarer

© 2022 - 2024 — McMap. All rights reserved.