Finding the loaded plugins?

Is there a way to find out which (gem) plugins are loaded without
repeating work the initializer has already done?

Michael

The problem is that the current Initializer instance isn’t saved anywhere.

If you change your environment.rb like this:

Init = Rails::Initializer.run …

Then you can read from it later:

Init.loaded_plugins.map &:name

That's not what I want, although I deliberately didn't say what I'm
trying to do. I'm currently hacking on the rails/info controller to make
it modular. I'd like to add a hook for plugins/gems as well as the
application to add their own diagnostic information to that controller.

There are, of course, several packages for introspecting a rails app
already, but I think there is room for a simple, very lightweight
standard hook for extensions to add information. Particularly, a hook
that is always available, not dependent on additional extensions.

More on this latter.

Michael

For gems, your best bet is to iterate over Gem.loaded_specs. That
should return everything that's been loaded. You'll need to look for a
rails/init.rb file to tell if it's a plugin.

--Matt Jones

No, but it's been proposed:
https://rails.lighthouseapp.com/projects/8994/tickets/2526

jeremy

As I've been hacking around in Railties anyway, I've changed to code to
my liking and moved loaded_plugins from Initializer to Configuration.

More on this latter.

Michael

I think that your goal, “get a list of loaded plugins”, is fairly straightforward and I don’t understand why we need to know what are you going to do with it. What I’m interested in is why do you think saving the Initializer instance isn’t adequate?

Rails saves the active Configuration instance, so for consistency it should also save the Initializer. After 2 additional lines of code we could access plugins like:

Rails.initializer.loaded_plugins

Because that's something the application programmer would have to do. I
was working inside of railties. See the parallel thread on
/rails/info/properties I just started.

Michael

I've done a little bit of thinking around this, and my preference
would be, roughly in order:

1) Rails.loaded_plugins
2) Rails.configuration.loaded_plugins
3) Rails.initializer.loaded_plugins

Ideally (and I think Yehuda touched on this slightly at RailsConf) I
feel there ought to be an instance which represents a booted Rails
application, which should know about which plugins have been loaded.
Then I'd hope have a method along the lines of Rails::App#plugins (the
'loaded' part is implied), or whatever.

Since no such object currently exists, accessing the set of currently
& successfully loaded plugins directly from the Rails constant seems
most consistent (i.e. along with Rails.root as the directory of the
currently running app, and Rails.configuration as the configuration
specification that was used during the boot of the currently running
app).

Rails.configuration.loaded_plugins seems relatively less-good because,
IMHO, the configuration object is more about specification than state.
It's where I tell Rails which plugins/gems to load, not the object
which actually has any responsibility for loading them. It seems like
having an object designed to describe database connection parameters,
and then deciding to store the actual connection instance in that
object too; not the most elegant design.

Rails.initializer.loaded_plugins is my "least favourite" because it
exposes the fact that Rails has an initializer, which I shouldn't
really need to care about; it's exposing an implementation detail
(plugins get loaded via some Initializer class), rather than providing
a clean and sensible API for finding out which plugins have loaded.

All this said, I do realise that the distinctions are incredibly (and
some might say pointlessly) subtle, and may be meaningless to
everyone bar me. Most importantly,and why I said 'least favourite'
above, *any* implementation would be better than none.

James

My patch at

https://rails.lighthouseapp.com/projects/8994/tickets/2684-modular-
rails-info

currently does 2). However, I agree with your argument and will change
it to 1).

Michael