my $config = $self->resolve( service => 'config' );
+ # don't force default_component to be undef if the config wasn't set
+ my @default_view = $config->{default_view}
+ ? ( default_component => $config->{default_view} )
+ : ( )
+ ;
+ my @default_model = $config->{default_model}
+ ? ( default_component => $config->{default_model} )
+ : ( )
+ ;
+
$self->add_sub_container(
$self->build_component_subcontainer
);
);
$self->add_sub_container(
- $self->build_view_subcontainer(
- default_component => $config->{default_view},
- )
+ $self->build_view_subcontainer( @default_view )
);
$self->add_sub_container(
- $self->build_model_subcontainer(
- default_component => $config->{default_model},
- )
+ $self->build_model_subcontainer( @default_model )
);
}
unless $comps{$component};
}
}
-
- $self->get_sub_container('model')->make_single_default;
- $self->get_sub_container('view')->make_single_default;
}
sub _fix_syntax {
return @result;
}
-# FIXME - t0m, how do you feel about this name?
-# also, do you think I should draw it here, or just return the data structure?
-sub get_components_names_types {
- my ( $self ) = @_;
- my @comps_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 = $sub_container->resolve(service => $service);
- my $compname = ref $comp || $comp;
- my $type = ref $comp ? 'instance' : 'class';
- push @comps_names_types, [ $compname, $type ];
- }
- }
-
- return @comps_names_types;
-}
-
sub get_all_components {
my $self = shift;
my %components;
my $component_service_name = "${type}_${name}";
- $self->get_sub_container('component')->add_service(
+ # The 'component' sub-container will create the object, and store it's
+ # instance, which, by default, will live throughout the application.
+ # The model/view/controller sub-containers only reference the instance
+ # held in the aforementioned sub-container, and execute the ACCEPT_CONTEXT
+ # sub every time they are called, when it exists.
+ my $instance_container = $self->get_sub_container('component');
+ my $accept_context_container = $self->get_sub_container($type);
+
+ $instance_container->add_service(
Catalyst::IOC::ConstructorInjection->new(
name => $component_service_name,
class => $component,
depends_on( '/config' ),
],
)
- );
+ ) unless $instance_container->has_service( $component_service_name );
+ # ^ custom containers might have added the service already.
+ # we don't want to override that.
- $self->get_sub_container($type)->add_service(
+ $accept_context_container->add_service(
Catalyst::IOC::BlockInjection->new(
name => $name,
dependencies => [
depends_on( "/component/$component_service_name" ),
],
- block => sub { return shift->param($component_service_name) },
+ block => sub { shift->param($component_service_name) },
)
- );
+ ) unless $accept_context_container->has_service( $name );
+ # ^ same as above
}
# FIXME: should this sub exist?
my @parts = split /::/, $component;
- while (my $type = shift @parts) {
+ while (scalar @parts > 1) {
+ my $type = shift @parts;
+
return ('controller', join '::', @parts)
if $type =~ /^(c|controller)$/i;
=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.
=head1 Building Services
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 }>.
+C<< <MyApp->config( 'Plugin::ConfigLoader' => { substitutions => { ... } } ) >>.
Example:
- MyApp->config->{ 'Plugin::ConfigLoader' }->{ substitutions } = {
- baz => sub { my $c = shift; qux( @_ ); }
- }
+ MyApp->config( 'Plugin::ConfigLoader' => {
+ substitutions => {
+ baz => sub { my $c = shift; qux( @_ ); },
+ },
+ });
The above will respond to C<__baz(x,y)__> in config strings.
$name is a regexp, it returns an array of matching components. Otherwise, it
looks for the component with name $name.
-=head2 get_components_names_types
-
-Gets all components from all containers and returns them as an array of
-arrayrefs containing the component name and the component type (i.e., whether
-it's an instance or a class).
-
=head2 get_all_components
Fetches all the components, in each of the sub_containers model, view and