Component Question

It appears that in Rails’s initializer.rb, the $LOAD_PATH is initialized
with the paths for all the components included in the app before the
models. This has the effect that if there is Foo class in your models
directory and a Foo class in a component you’ve included, the Rails
loader loads the component and not the model from your models directory.

While you could namespace the component to avoid conflicts, it seems
like a valid strategy for customizing your component would be to
redefine portions of the model from the component in an entry in your
models directory. However, since the Rails $LOAD_PATH results in the
models directory entry not being read, this seems impossible. Am I
overlooking something/overlooking a better strategy to achieve this
functionality? Is there a particular reason for this ordering I’m
overlooking?

Thanks,
Fred

I doubt that the ordering of the load paths in this particular case is
anything beyond an artefact of the order various parts of the Rails
framework are initialized, and as such it shouldn’t be a problem to
switch them around.

Your best bet is to simply alter the $LOAD_PATH directly yourself,
such that the component paths are pushed after the application ones;
this shouldn’t be too hard to do, and could be shared between each of
your applications via a plugin (or just a single method in a file
somewhere).

That said, it still wouldn’t be possible to redefine only portions of
the Foo class - Ruby will only load the first one it sees (either from
the application, or the component), and will completely ignore the
other. The overloading features that the engines plugin provides might
possibly help you, in some cases.

  • james

James A. wrote:

I doubt that the ordering of the load paths in this particular case is
anything beyond an artefact of the order various parts of the Rails
framework are initialized, and as such it shouldn’t be a problem to
switch them around.

Your best bet is to simply alter the $LOAD_PATH directly yourself,
such that the component paths are pushed after the application ones;
this shouldn’t be too hard to do, and could be shared between each of
your applications via a plugin (or just a single method in a file
somewhere).

That said, it still wouldn’t be possible to redefine only portions of
the Foo class - Ruby will only load the first one it sees (either from
the application, or the component), and will completely ignore the
other. The overloading features that the engines plugin provides might
possibly help you, in some cases.

  • james

Thanks for the response. Turns out $LOAD_PATH is immutable, but you can
work with config.load_paths in the initializer, which provided at least
a stopgap solution. While Ruby won’t keep on searching, if you have the
model from the app’s file loaded up first, you can do some variety of
dependency via the ActiveSupport Dependencies class to include the
component version, and it all works nicely (whereas the other way would
require sacrificing a lot of portability in the component).

2006/7/20, Fred W. [email protected]:

your applications via a plugin (or just a single method in a file
somewhere).

work with config.load_paths in the initializer, which provided at least
a stopgap solution. While Ruby won’t keep on searching, if you have the
model from the app’s file loaded up first, you can do some variety of
dependency via the ActiveSupport Dependencies class to include the
component version, and it all works nicely (whereas the other way would
require sacrificing a lot of portability in the component).

$:, which should be equivalent to $LOAD_PATH, isn’t immutable.

You can do $:.insert … or $:.append.

It’s used many time in Rails core.