Plugin load paths & load order

Messing around with the plugin loading mechanism (as I love to do), I
stumbled on a $LOAD_PATH oddity and I was wondering if I'm missing the
reasoning behind it. At the moment, plugin lib directories are added
to the $LOAD_PATH by two independent mechanisms:

    * Rails::Initializer#load_plugins adds them when the plugin is loaded
    * Rails::Initializer::Configuration#default_load_paths includes
them by default

This behaviour seems broken in the light of the config.plugins; if I
have chosen to control the plugins I need to load, other plugin lib
directories simply shouldn't be available to Rails.

If there's a reason for this, I'd love to know; alternatively, there's
a tiny patch here: http://dev.rubyonrails.org/ticket/6842

Also, while I've got your attention, I noticed a while back that Koz
suggested that plugin load order could be controlled by
config.plugins:

  "The recent addition of config.plugins will let you specify which
plugins to load, and which order to load them in."
(http://dev.rubyonrails.org/ticket/6418)

This, alas, isn't the case. Is there any support for having Rails
respect the order that plugins are specified in on config.plugins?
Rather than being anything approaching "plugin dependencies" (spit,
gag, splutter), this just adds a bit more meaning to an existing
configuration option....

Also reported here: http://dev.rubyonrails.org/ticket/6571

James Adam wrote:

  "The recent addition of config.plugins will let you specify which
plugins to load, and which order to load them in."
(http://dev.rubyonrails.org/ticket/6418)

config.plugins prevents the init.rb from being called, meaning the
plugins 'lie dormant'. What's the scenario we're trying to prevent by
stopping them from appearing on the load paths?

Having said that, a patch to tidy all that up, and make config.plugins
a little more powerful does seem reasonable.

> "The recent addition of config.plugins will let you specify which
> plugins to load, and which order to load them in."
> (http://dev.rubyonrails.org/ticket/6418)

config.plugins prevents the init.rb from being called, meaning the
plugins 'lie dormant'. What's the scenario we're trying to prevent by
stopping them from appearing on the load paths?

The issue would be where a 'disabled' plugin contains a class with the
same name as something lower down in the load path, i.e. a plugin with
the file 'struct.rb' will always be loaded rather than one from the
Ruby lib paths (which are by default at the end of the load path).

I think it's fairly unlikely that something like this would come up in
practice, but it's worth cleaning the load path just for the sake of
being a good citizen, and if Rails suggests that you can disable a
plugin by not including it in config.plugins, it really should ensure
that the plugin has no affect on the running application unless it is
enabled.

Having said that, a patch to tidy all that up, and make config.plugins
a little more powerful does seem reasonable.

More than happy to do this. Obrie marked my original patch as a
duplicate to his own, although I'm not sure that they have the same
effect - it depends on when $LOAD_PATH.uniq! is called, and the
behaviour of Array#uniq!; while at the moment both patches are
effective, I think it's just clearer to have a single point where
plugin lib directories are dealt with, and that should be in
load_plugin().

I'll repost to this thread with a patch making config.plugins a little
more powerful soon.

Cheers!

As promised: http://dev.rubyonrails.org/ticket/6851

Is there *any* chance that this change might be included in 1.2?....
*grovels* :wink:

I've left out the changes to ensure that plugin lib directories only
appear in the $LOAD_PATH once; I'd suggest you choose from

* http://dev.rubyonrails.org/ticket/6842 - remove plugins from the
default_load_paths
* http://dev.rubyonrails.org/ticket/6571 - add a trailing slash when
loading plugins and then use $LOAD_PATH.uniq! to clear out duplicates

... they're both tiny & clean patches that should do the job. IMHO
#6842 is a cleaner and 'more correct' way to resolve the duplication,
but either way the duplicates are cleared.

Cheers guys,

I agree with James. I'm not really sure why it was added there in the
first place (plus it's really not correct either since it doesn't add
plugins in subdirectories). So with his solution, we get fix 2
problems with 1 stone.

James Adam wrote:

It occurred to me on the walk home that our two patches solve slightly
different problems; adding the trailing slash to paths added by
load_plugin won't prevent all plugin lib directories being added to
the $LOAD_PATH, it will only prevent duplicates. My original query was
with why all the plugin libr directories were being added regardless
of the contents of config.plugins...

But anyway, I've rolled in your 'trailing-slash' fix into the patch on
Ticket #6842, so that should kill every bird with one tiny pebble :slight_smile:

No brainer patch to apply: http://dev.rubyonrails.org/ticket/6842

Cheers

No brainer patch to apply: http://dev.rubyonrails.org/ticket/6842

Applied this and 6851 to trunk and 1.2. Thanks!

Hey guys, I thought we were all ready for a new Rails 1.2 RC, but I
just realized I had cache_classes=true in one of my apps, and it
started bombing as soon as I changed it back. So here's the
changeset: http://dev.rubyonrails.org/changeset/5801

Nicholas' load_once_path changes were working, but none of the plugin
paths were ever being added to it. #default_load_once_paths in
Rails::Initializer wasn't working because it runs before plugins are
initialized (and plugin lib paths aren't in default_load_paths). So,
I just forced an addition to Dependencies.load_once_paths in
#load_plugin.

This change seems to work, but it makes it so no plugins reload at all
(which has been the current behavior of plugins since the beginning).
However, if you do want your plugins to reload, you can just add this
to the top of init.rb:

Dependencies.load_once_paths.delete(lib_path)

Any problems with this approach? I just don't think all these plugins
have been written to deal with reloading, so I don't want to force
folks to restructure them. Maybe this can be changed for Rails 2.0
though...

Sounds good to me Rick.