merge gsoc_breadboard_moved_setup_component
André Walker [Mon, 25 Jul 2011 23:06:05 +0000 (20:06 -0300)]
TODO
lib/Catalyst/IOC/Container.pm
lib/Catalyst/IOC/SubContainer.pm
t/lib/TestAppPathBug.pm
t/lib/TestAppPathBug/Controller/Root.pm [new file with mode: 0644]

diff --git a/TODO b/TODO
index 8fd77ad..01bcb84 100644 (file)
--- a/TODO
+++ b/TODO
@@ -54,3 +54,51 @@ http://github.com/willert/catalyst-plugin-log4perl-simple/tree
   - Profit! (Things like changing the complete app config per vhost, i.e.
     writing a config loader / app class role which dispatches per vhost to
     differently configured apps is piss easy)
+
+## GSOC
+
+### Next large steps:
+
+  - Moving setup_components etc into the container
+
+    - This is so that you can just load the container and get models etc from it,
+      without loading Catalyst.
+
+    - Finish moving setup_component
+        - $component->COMPONENT() is still called by setup_component
+          (should there be a Service::WithCOMPONENT to solve this?)
+        - make it a method, not function
+
+    - Break $instance->expand_modules() in setup_components and figure
+      out later how to bring it back
+
+    - Move expand_component_module
+
+    - Move locate_components
+
+    - Move contents of setup_components
+
+  - Finished documentation for ::IOC parts.
+
+  - Creating service()-like sugar for component
+
+  - Test cases for extending the container in an application.
+    - Using the sugar added in the previous item
+    - Test when Model::Foo depends_on Model::Bar
+
+  - Allowing people to change component lifecycles
+
+    - This is done by being able to use an alternate Service class..
+
+      I.E. We currently force everything to do Catalyst/IOC/Service/WithAcceptContext.pm, but
+      things without an ACCEPT_CONTEXT could just not bother, and it would be nice to have
+      one that cached the object in request scope (i.e. Catalyst::Component::InstancePerContext)
+      etc.
+
+      However we need to work out an interface for people to setup / configure this.
+
+### To polish off
+
+  - Document current methods
+  - +    $class->container->get_sub_container('model')->make_single_default;
++    $class->container->get_sub_container('view')->make_single_default;
index bfd1004..040dc83 100644 (file)
@@ -39,7 +39,7 @@ has substitutions => (
 has name => (
     is      => 'ro',
     isa     => 'Str',
-    default => 'TestApp',
+    default => 'MyApp',
 );
 
 has sub_container_class => (
@@ -79,6 +79,7 @@ sub BUILD {
         $self->build_controller_subcontainer
     );
 
+    # FIXME - the config should be merged at this point
     my $config        = $self->resolve( service => 'config' );
     my $default_view  = $params->{default_view}  || $config->{default_view};
     my $default_model = $params->{default_model} || $config->{default_model};
@@ -409,6 +410,7 @@ sub get_component_from_sub_container {
         return $sub_container->get_component( $default, $c, @args )
             if $default && $sub_container->has_service( $default );
 
+        # FIXME - should I be calling $c->log->warn here?
         # this is never a controller, so this is safe
         $c->log->warn( "Calling \$c->$sub_container_name() is not supported unless you specify one of:" );
         $c->log->warn( "* \$c->config(default_$sub_container_name => 'the name of the default $sub_container_name to use')" );
@@ -447,7 +449,7 @@ sub find_component {
               ;
 
     for my $subcontainer_name (qw/model view controller/) {
-        my $subcontainer = $self->get_sub_container($subcontainer_name);
+        my $subcontainer = $self->get_sub_container( $subcontainer_name );
         my @components   = $subcontainer->get_service_list;
         @result          = grep { m{$component} } @components;
 
@@ -455,6 +457,7 @@ sub find_component {
             if @result;
     }
 
+    # FIXME - I guess I shouldn't be calling $c->components here
     # one last search for things like $c->comp(qr/::M::/)
     @result = $self->find_component_regexp(
         $c->components, $component, $c, @args
@@ -608,22 +611,44 @@ __END__
 
 Catalyst::Container - IOC for Catalyst components
 
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
 =head1 METHODS
 
+=head1 Containers
+
 =head2 build_model_subcontainer
 
+Container that stores all models.
+
 =head2 build_view_subcontainer
 
+Container that stores all views.
+
 =head2 build_controller_subcontainer
 
+Container that stores all controllers.
+
+=head1 Services
+
 =head2 build_name_service
 
+Name of the application.
+
 =head2 build_driver_service
 
+Config options passed directly to the driver being used.
+
 =head2 build_file_service
 
+?
+
 =head2 build_substitutions_service
 
+Executes all the substitutions in config. See L</_config_substitutions> method.
+
 =head2 build_extensions_service
 
 =head2 build_prefix_service
@@ -646,24 +671,80 @@ Catalyst::Container - IOC for Catalyst components
 
 =head2 build_config_local_suffix_service
 
-=head2 get_component_from_sub_container
+Determines the suffix of files used to override the main config. By default
+this value is C<local>, which will load C<myapp_local.conf>.  The suffix can
+be specified in the following order of preference:
+
+=over
+
+=item * C<$ENV{ MYAPP_CONFIG_LOCAL_SUFFIX }>
+
+=item * C<$ENV{ CATALYST_CONFIG_LOCAL_SUFFIX }>
+
+=back
+
+The first one of these values found replaces the default of C<local> in the
+name of the local config file to be loaded.
+
+For example, if C< $ENV{ MYAPP_CONFIG_LOCAL_SUFFIX }> is set to C<testing>,
+ConfigLoader will try and load C<myapp_testing.conf> instead of
+C<myapp_local.conf>.
+
+=head2 get_component_from_sub_container($sub_container, $name, $c, @args)
+
+Looks for components in a given subcontainer (such as controller, model or view), and returns the searched component. If $name is undef, it returns the default component (such as default_view, if $sub_container is 'view'). If $name is a regexp, it returns an array of matching components. Otherwise, it looks for the component with name $name.
 
 =head2 get_components_types
 
 =head2 get_all_components
 
+Fetches all the components, in each of the sub_containers model, view and controller, and returns a readonly hash. The keys are the class names, and the values are the blessed objects. This is what is returned by $c->components.
+
 =head2 add_component
 
+Adds a component to the appropriate subcontainer. The subcontainer is guessed by the component name given.
+
 =head2 find_component
 
+Searches for components in all containers. If $component is the full class name, the subcontainer is guessed, and it gets the searched component in there. Otherwise, it looks for a component with that name in all subcontainers. If $component is a regexp, it calls the method below, find_component_regexp, and matches all components against that regexp.
+
 =head2 find_component_regexp
 
+Finds components that match a given regexp. Used internally, by find_component.
+
 =head2 setup_component
 
 =head2 _fix_syntax
 
 =head2 _config_substitutions
 
+This method substitutes macros found with calls to a function. There are a
+number of default macros:
+
+=over
+
+=item * C<__HOME__> - replaced with C<$c-E<gt>path_to('')>
+
+=item * C<__ENV(foo)__> - replaced with the value of C<$ENV{foo}>
+
+=item * C<__path_to(foo/bar)__> - replaced with C<$c-E<gt>path_to('foo/bar')>
+
+=item * C<__literal(__FOO__)__> - leaves __FOO__ alone (allows you to use
+C<__DATA__> as a config value, for example)
+
+=back
+
+The parameter list is split on comma (C<,>). You can override this method to
+do your own string munging, or you can define your own macros in
+C<MyApp-E<gt>config-E<gt>{ 'Plugin::ConfigLoader' }-E<gt>{ substitutions }>.
+Example:
+
+    MyApp->config->{ 'Plugin::ConfigLoader' }->{ substitutions } = {
+        baz => sub { my $c = shift; qux( @_ ); }
+    }
+
+The above will respond to C<__baz(x,y)__> in config strings.
+
 =head1 AUTHORS
 
 Catalyst Contributors, see Catalyst.pm
index afa8e3f..9ac735c 100644 (file)
@@ -6,8 +6,8 @@ use Catalyst::IOC::BlockInjection;
 extends 'Bread::Board::Container';
 
 has default_component => (
-    isa => 'Str|Undef',
-    is  => 'ro',
+    isa      => 'Str|Undef',
+    is       => 'ro',
     required => 0,
     writer   => '_set_default_component',
 );
@@ -31,7 +31,8 @@ sub get_component_regexp {
     return @result;
 }
 
-# FIXME: not the best name for a sub
+# FIXME - is this sub ok?
+# is the name ok too?
 sub make_single_default {
     my ( $self ) = @_;
 
@@ -51,14 +52,24 @@ __END__
 
 Catalyst::IOC::SubContainer - Container for models, controllers and views
 
+=head1 SYNOPSIS
+
+=head1 DESCRIPTION
+
 =head1 METHODS
 
 =head2 get_component
 
+Gets the service of the container for the searched component. Also executes the ACCEPT_CONTEXT sub in the component, if it exists.
+
 =head2 get_component_regexp
 
+Gets all components from container that match a given regexp.
+
 =head2 make_single_default
 
+If the container has only one component, and no default has been defined, this method makes that one existing service the default.
+
 =head1 AUTHORS
 
 Catalyst Contributors, see Catalyst.pm
index 74a2f27..7ae5f5b 100644 (file)
@@ -1,9 +1,6 @@
-use strict;
-use warnings;
-
 package TestAppPathBug;
-use strict;
-use warnings;
+use Moose;
+extends 'Catalyst';
 use Catalyst;
 
 our $VERSION = '0.01';
@@ -13,15 +10,9 @@ __PACKAGE__->config( name => 'TestAppPathBug', root => '/some/dir' );
 __PACKAGE__->log(TestAppPathBug::Log->new);
 __PACKAGE__->setup;
 
-sub foo : Path {
-    my ( $self, $c ) = @_;
-    $c->res->body( 'This is the foo method.' );
-}
-
 package TestAppPathBug::Log;
-use strict;
-use warnings;
-use base qw/Catalyst::Log/;
+use Moose;
+extends 'Catalyst::Log';
 
 sub warn {}
 
diff --git a/t/lib/TestAppPathBug/Controller/Root.pm b/t/lib/TestAppPathBug/Controller/Root.pm
new file mode 100644 (file)
index 0000000..b28d6b3
--- /dev/null
@@ -0,0 +1,14 @@
+package TestAppPathBug::Controller::Root;
+use Moose;
+use namespace::autoclean;
+
+BEGIN { extends 'Catalyst::Controller' };
+
+__PACKAGE__->config(namespace => '');
+
+sub foo : Path {
+    my ( $self, $c ) = @_;
+    $c->res->body( 'This is the foo method.' );
+}
+
+1;