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.
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....
"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.
... 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.
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.
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
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...