[Catalyst-commits] r7298 -
trunk/examples/CatalystAdvent/root/2007/pen
jshirley at dev.catalyst.perl.org
jshirley at dev.catalyst.perl.org
Fri Dec 14 18:27:44 GMT 2007
Author: jshirley
Date: 2007-12-14 18:27:44 +0000 (Fri, 14 Dec 2007)
New Revision: 7298
Added:
trunk/examples/CatalystAdvent/root/2007/pen/CatalystConfig.pod
Log:
Adding Catalyst Configuration internal pod... LTJake review please, thanks
Added: trunk/examples/CatalystAdvent/root/2007/pen/CatalystConfig.pod
===================================================================
--- trunk/examples/CatalystAdvent/root/2007/pen/CatalystConfig.pod (rev 0)
+++ trunk/examples/CatalystAdvent/root/2007/pen/CatalystConfig.pod 2007-12-14 18:27:44 UTC (rev 7298)
@@ -0,0 +1,153 @@
+=head1 Catalyst Configuration: A to Z
+
+A common question, and in some cases turns to bad assumptions, is how to
+properly setup configuration in various Catalyst components. This article
+should hopefully shed some light.
+
+=head2 First things first: What's a component
+
+In Catalyst every Model, View and Controller class is a component. It's just
+the basic default object that the big 3 inherit from (quite literally, as they
+come from L<Catalyst::Component>.)
+
+When Catalyst starts up, the point in time where initialization of each of the
+application components is called "component time". It's the step after compile
+time, and the time before Catalyst is dispatching and serving requests. When
+debugging is enabled, Catalyst gives you a listing of components that are
+loaded at this time:
+
+ [debug] Loaded components:
+ .-----------------------------------------------------------------+----------.
+ | Class | Type |
+ +-----------------------------------------------------------------+----------+
+ | ConfigEg::Controller::Root | instance |
+ | ConfigEg::Model::Bar | instance |
+ | ConfigEg::Model::Foo | instance |
+ '-----------------------------------------------------------------+----------'
+
+As you can see, this is the controller and models that are loaded in the
+application. They don't necessarily have to exist on disk, as
+L<Catalyst::Model::DBIC::Schema> creates classes dynamically based on the
+classes loaded from L<DBIx::Class>.
+
+Each of these components listed runs the C<sub COMPONENT> method, and at this
+point the configuration is usable.
+
+=head2 Configuration: App versus Component
+
+The breakdown of the application level configuration and component level
+configuration is the best way to differentiate configuration spaces.
+
+Catalyst gives you a very nice convention to isolate configuration to a
+specific component at the app level, by merely naming that configuration key.
+
+Above, we listed a C<ConfigEg::Model::Foo> so if we want to configure it in
+the ConfigEg.pm file, or in configeg.yml, all we have to do is write out
+the prefix:
+
+ ---
+ name: ConfigEg
+ "Model::Foo":
+ config: "Specific just to ConfigEg::Model::Foo!"
+
+(Note: You do not include your application prefix! Everything after MyApp::)
+
+To check this, inside the C<ConfigEg/Model/Foo.pm> file, you can overload
+the C<sub COMPONENT> method with something like this:
+
+ sub COMPONENT {
+ my $self = shift->next::method(@_);
+ print dump( $self );
+ return $self;
+ }
+
+This will dump out:
+
+ bless({ config => "Specific just to ConfigEg::Model::Foo" }, "ConfigEg::Model::Foo")
+
+Piece of cake!
+
+=head2 Component Configuration
+
+Now, inside of the C<ConfigEg/Model/Foo.pm> file if you want to specify default
+configuration, you don't need to prefix the configuration keys. You just
+start out with:
+
+ __PACKAGE__->config(
+ config => 'This will be overridden, but is a nice default'
+ );
+
+Now, if you were to remove the entries in configeg.yml for Model::Foo, this
+config would take precedence.
+
+=head2 ConfigLoader: The Aptly Named Configuration Loader
+
+The great thing that L<Catalyst::Plugin::ConfigLoader> does for you is merging
+the various configurations. Rather than simply overwrite the entirety of
+a components configuration, it will merge them giving precedence up the chain
+towards "human editability".
+
+The lowest is the component package (ConfigEg/Model/Foo.pm), up next is
+ConfigEg.pm and the last step is the individual configuration files. By default
+this would be configeg.yml and the final word is configeg_local.yml
+
+By merging, what happens is if you have the following (completely and totally
+fabricated) structure in the component package C<ConfigEg/Model/Foo.pm>:
+
+ __PACKAGE__->config(
+ paper_bag => {
+ pickles => 10,
+ sandwich => 1,
+ relish => 5,
+ }
+ );
+
+And then inside of C<ConfigEg.pm> you have:
+
+ __PACKAGE__->config(
+ name => 'ConfigEg',
+ 'Model::Foo' => {
+ paper_bag => { pickles => 0 }
+ }
+ );
+
+And finally in configeg.yml you have:
+ ---
+ name: ConfigEg
+ "Model::Foo":
+ paper_bag:
+ pickles: 1
+ cheese: 5
+
+The final merged structure would be:
+ paper_bag => {
+ cheese => 5,
+ pickles => 1,
+ relish => 5,
+ sandwich => 1
+ }
+
+As you can see, the configeg.yml has the highest precedence by setting 'pickles'
+to 1 (rather than 0 which is specified in C<ConfigEg.pm> or 10 specified in
+C<ConfigEg/Model/Foo.pm>) and it introduces an entirely new key 'cheese'.
+
+=head2 Real World Usage
+
+If you don't like lunch items, just think of ways a component base class can
+specify default configuration to be overriden by a specific MyApp:: instance of
+that class and then finally overridden by the configuration files.
+
+If there is a base component model that is highly generic, it may have a set
+of configuration options present that just describe the basic required config.
+
+When it is created in an application (say, from a Catalyst::Helper package) then
+it may create or duplicate those same configuration settings (like the way
+C<Catalyst::View::TT> bootstraps itself). It then expects final configuration
+to be done in the application config (myapp.yml, or whatever your config choice
+may be)
+
+=head1 Author
+
+J. Shirley <jshirley at cpan.org>
+
+=cut
More information about the Catalyst-commits
mailing list