On Apr 10, 2013, at 11:50 PM, Peter Meier <[email protected]> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi Luke,
>
> thanks for your answer.
>
>> I'm confident there's an easier way; just the way you're using the
>> autoloader there seems unecessarily complicated. Why are you even
>> using autoloading? Why don't you just hard-code the invalidator
>> name, and use normal 'require' or something similar?
>
> Because the invalidator should be pluggable, means that people should
> be able to deliver their own version of the invalidator in their own
> modules and just configure my terminus to use their implementation of
> the invalidator.
>
> So as far as my experience goes, I can't simply require a file that is
> delivered by modules, that's why I started using the autoloader, which
> walks through all lib dirs of the modules and loads the found one. Or
> I'm wrong with my understanding how lib code is loaded?
>
> Distributing the terminus in an own module works well and it's also
> loaded after being configured in routes.yaml. But what's about
> additional code for that terminus, that should also be loaded and
> plugged in based on an own configuration option for that terminus?
The autoloader seemed like a good idea at the time, but over the years we've
found both that it's often more complicated than you really need, and it
actively works against you sometimes. In particular, I think the dev team
(i.e., not me) is working on fixing some major issues resulting from the fact
that ruby can't search the module lib dirs. In other words, the autoloader
works fine for Puppet plugins, but it works less well for, say, required
libraries. In your example, if someone distributed two libraries, and you used
the autoloader to load one and it tried to use ruby to load the other, you'd
get a failure.
That isn't to say you shouldn't use it, just that it's not a slam dunk.
Note that if 'require' works, you can require based on passed-in values:
require "path/to/#{library}"
It does look like the autoloader is your best bet at this point, though, and
the question becomes, how do you the class name.
This is one of those things that always surprised me about ruby: How hard it
was to convert back and forth between class names and objects. My solution to
that in Puppet is, well, to never talk about classes. You'll notice I just
about always use things like Puppet::Type.type(:file), instead of
Puppet::Type::File.
Basically, I built a load+register system for all plugins that load: Every
plugin has to register itself with something, and the way you get the class is
to ask for that registration system. Notice that you define a type like this:
Puppet::Type.newtype(:foo)
Instead of:
class Puppet::Type::Foo
This is pretty much exactly to avoid the kind of constant munging you're doing.
You're probably right that there's some Puppet code to convert back and forth.
You might check out puppet/util/constant_inflector.rb, which gets you close.
There's also a bunch of related code in util/classgen.rb, but, um, there be
dragons. It's basically a system for loading and managing subclasses of
things (which, you might have noticed, is a constant pattern in Puppet for
basically all plugins). If you're really just loading a terminus, chances are
that the code you want is already available via classgen and is already usable
to you, you just need to, well, understand how that system works.
--
Luke Kanies | http://about.me/lak | http://puppetlabs.com/ | +1-615-594-8199
Join us at PuppetConf 2013, August 22-23 in San Francisco -
http://bit.ly/pupconf13
--
You received this message because you are subscribed to the Google Groups
"Puppet Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/puppet-dev?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.