pod for build_component_subcontainer
[catagits/Catalyst-Runtime.git] / lib / Catalyst / IOC / Container.pm
index c646d84..2569d1d 100644 (file)
@@ -8,6 +8,7 @@ use Devel::InnerPackage ();
 use Hash::Util qw/lock_hash/;
 use MooseX::Types::LoadableClass qw/ LoadableClass /;
 use Moose::Util;
+use Catalyst::IOC::BlockInjection;
 use Catalyst::IOC::ConstructorInjection;
 use Module::Pluggable::Object ();
 use namespace::autoclean;
@@ -39,9 +40,9 @@ has substitutions => (
 );
 
 has application_name => (
-    is      => 'ro',
-    isa     => 'Str',
-    default => 'MyApp',
+    is       => 'ro',
+    isa      => 'Str',
+    required => 1,
 );
 
 has sub_container_class => (
@@ -82,6 +83,10 @@ sub BUILD {
     my $config = $self->resolve( service => 'config' );
 
     $self->add_sub_container(
+        $self->build_component_subcontainer
+    );
+
+    $self->add_sub_container(
         $self->build_controller_subcontainer
     );
 
@@ -122,6 +127,14 @@ sub build_controller_subcontainer {
     );
 }
 
+sub build_component_subcontainer {
+    my $self = shift;
+
+    return Bread::Board::Container->new(
+        name => 'component',
+    );
+}
+
 sub build_application_name_service {
     my $self = shift;
 
@@ -542,12 +555,12 @@ sub get_component_from_sub_container {
 }
 
 sub find_component {
-    my ( $self, $component, $c, @args ) = @_;
+    my ( $self, $component, @args ) = @_;
     my ( $type, $name ) = _get_component_type_name($component);
     my @result;
 
     return $self->get_component_from_sub_container(
-        $type, $name, $c, @args
+        $type, $name, @args
     ) if $type;
 
     my $query = ref $component
@@ -560,14 +573,13 @@ sub find_component {
         my @components   = $subcontainer->get_service_list;
         @result          = grep { m{$component} } @components;
 
-        return map { $subcontainer->get_component( $_, $c, @args ) } @result
+        return map { $subcontainer->get_component( $_, @args ) } @result
             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
+        $component, @args
     ) if !@result and ref $component;
 
     # it expects an empty list on failed searches
@@ -575,10 +587,10 @@ sub find_component {
 }
 
 sub find_component_regexp {
-    my ( $self, $components, $component, @args ) = @_;
+    my ( $self, $component, @args ) = @_;
     my @result;
 
-    my @components = grep { m{$component} } keys %{ $components };
+    my @components = grep { m{$component} } keys %{ $self->get_all_components };
 
     for (@components) {
         my ($type, $name) = _get_component_type_name($_);
@@ -600,7 +612,7 @@ sub get_components_names_types {
     for my $sub_container_name (qw/model view controller/) {
         my $sub_container = $self->get_sub_container($sub_container_name);
         for my $service ( $sub_container->get_service_list ) {
-            my $comp     = $self->resolve(service => $service);
+            my $comp     = $sub_container->resolve(service => $service);
             my $compname = ref $comp || $comp;
             my $type     = ref $comp ? 'instance' : 'class';
             push @comps_names_types, [ $compname, $type ];
@@ -614,18 +626,14 @@ sub get_all_components {
     my $self = shift;
     my %components;
 
-    my $containers = {
-        map { $_ => $self->get_sub_container($_) } qw(model view controller)
-    };
+    my $container = $self->get_sub_container('component');
 
-    for my $container (keys %$containers) {
-        for my $component ($containers->{$container}->get_service_list) {
-            my $comp = $containers->{$container}->resolve(
-                service => $component
-            );
-            my $comp_name = ref $comp || $comp;
-            $components{$comp_name} = $comp;
-        }
+    for my $component ($container->get_service_list) {
+        my $comp = $container->resolve(
+            service => $component
+        );
+        my $comp_name = ref $comp || $comp;
+        $components{$comp_name} = $comp;
     }
 
     return lock_hash %components;
@@ -637,25 +645,27 @@ sub add_component {
 
     return unless $type;
 
-    $self->get_sub_container($type)->add_service(
+    my $component_service_name = "${type}_${name}";
+
+    $self->get_sub_container('component')->add_service(
         Catalyst::IOC::ConstructorInjection->new(
-            name      => $name,
+            name      => $component_service_name,
             class     => $component,
+            lifecycle => 'Singleton',
             dependencies => [
                 depends_on( '/application_name' ),
                 depends_on( '/config' ),
             ],
-            parameters => {
-                suffix => {
-                    isa => 'Str',
-                    default => Catalyst::Utils::class2classsuffix( $component ),
-                },
-                accept_context_args => {
-                    isa => 'ArrayRef|Undef',
-                    required => 0,
-                    default => undef,
-                },
-            },
+        )
+    );
+
+    $self->get_sub_container($type)->add_service(
+        Catalyst::IOC::BlockInjection->new(
+            name         => $name,
+            dependencies => [
+                depends_on( "/component/$component_service_name" ),
+            ],
+            block => sub { return shift->param($component_service_name) },
         )
     );
 }
@@ -705,17 +715,27 @@ Catalyst::Container - IOC for Catalyst components
 
 =head1 Building Containers
 
+=head2 build_component_subcontainer
+
+Container that stores all components, i.e. all models, views and controllers
+together. Each service is an instance of the actual component, and by default
+it lives while the application is running. Retrieving components from this
+subcontainer will instantiate the component, if it hasn't been instantiated
+already, but will not execute ACCEPT_CONTEXT.
+
 =head2 build_model_subcontainer
 
-Container that stores all models.
+Container that stores references for all models that are inside the components
+subcontainer. Retrieving a model triggers ACCEPT_CONTEXT, if it exists.
 
 =head2 build_view_subcontainer
 
-Container that stores all views.
+Same as L<build_model_subcontainer>, but for views.
 
 =head2 build_controller_subcontainer
 
-Container that stores all controllers.
+Same as L<build_model_subcontainer>, but for controllers. The difference is
+that there is no ACCEPT_CONTEXT for controllers.
 
 =head1 Building Services