From e6019e8a4187426482e18ebf80cc0ba482614486 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 27 Dec 2012 06:19:17 -0600 Subject: sketch out containers --- lib/Bread/Board.pm | 60 ++++++++++++++++++++++++++++--- t/010_container.t | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 t/010_container.t diff --git a/lib/Bread/Board.pm b/lib/Bread/Board.pm index aba64df..d1d6385 100644 --- a/lib/Bread/Board.pm +++ b/lib/Bread/Board.pm @@ -1,9 +1,11 @@ use v6; +class Bread::Board::Container {...} class Bread::Board::Dependency {...} role Bread::Board::Service { has Str $.name; + has Bread::Board::Container $.parent is rw = Bread::Board::Container; # XXX not sure how to make these optional - specifying the types here # makes it fail when the parameters aren't passed @@ -16,10 +18,11 @@ role Bread::Board::Service { method new (*%params is copy) { if %params. { my $deps = {}; - for %params..keys -> $dep { - $deps.{$dep} = Bread::Board::Dependency.new( - service => %params..{$dep}, - ); + for %params..keys -> $name { + my $dep = %params..{$name}; + $deps.{$name} = $dep.isa(Bread::Board::Dependency) + ?? $dep + !! Bread::Board::Dependency.new(service => $dep); } %params. = $deps; } @@ -121,3 +124,52 @@ class Bread::Board::Literal does Bread::Board::Service { return $.value; } } + +class Bread::Board::Container { + has Str $.name; + has Bread::Board::Container $.parent is rw = Bread::Board::Container; + # XXX again, as above + # has Hash of Bread::Board::Container $.sub_containers = {}; + # has Hash of Bread::Board::Service $.services = {}; + has $.sub_containers = {}; + has $.services = {}; + + # XXX again, as above + method new (*%params is copy) { + if %params..isa(Array) { + %params. = %params..map(-> $c { $c.name => $c }).hash; + } + if %params..isa(Array) { + %params. = %params..map(-> $c { $c.name => $c }).hash; + } + my $container = callwith(|%params); + if %params.:exists { + for %params..values -> $c { + $c.parent = $container; + } + } + if %params.:exists { + for %params..values -> $c { + $c.parent = $container; + } + } + return $container; + } + + method add_sub_container (Bread::Board::Container $c) { + $.sub_containers.{$c.name} = $c; + $c.parent = self; + } + + method get_sub_container (Str $name) { + return $.sub_containers.{$name}; + } + + method has_services { + return $.services > 0; + } + + method get_service (Str $name) { + return $.services.{$name}; + } +} diff --git a/t/010_container.t b/t/010_container.t new file mode 100644 index 0000000..379950a --- /dev/null +++ b/t/010_container.t @@ -0,0 +1,102 @@ +use v6; +use Test; + +use Bread::Board; + +sub does_ok(Mu $var, Mu $type, $msg = ("The object does '" ~ $type.perl ~ "'")) { + ok($var.does($type), $msg); +} + +class MyApp::Schema {} +class MyApp::View::TT {} + +my $c = Bread::Board::Container.new(name => '/'); +isa_ok($c, Bread::Board::Container); + +$c.add_sub_container( + Bread::Board::Container.new( + name => 'Application', + sub_containers => [ + Bread::Board::Container.new( + name => 'Model', + services => [ + Bread::Board::Literal.new(name => 'dsn', value => ''), + Bread::Board::ConstructorInjection.new( + name => 'schema', + class => MyApp::Schema, + dependencies => { + dsn => Bread::Board::Dependency.new( + service_path => '../dsn', + ), + user => Bread::Board::Literal.new( + name => 'user', + value => '', + ), + pass => Bread::Board::Literal.new( + name => 'pass', + value => '', + ), + }, + ), + ], + ), + Bread::Board::Container.new( + name => 'View', + services => [ + Bread::Board::ConstructorInjection.new( + name => 'TT', + class => MyApp::View::TT, + dependencies => { + tt_include_path => Bread::Board::Literal.new( + name => 'include_path', + value => [], + ), + }, + ), + ], + ), + Bread::Board::Container.new( + name => 'Controller', + ), + ], + ), +); + +my $app = $c.get_sub_container('Application'); +isa_ok($app, Bread::Board::Container); + +is($app.name, 'Application'); + +{ + my $controller = $app.get_sub_container('Controller'); + isa_ok($controller, Bread::Board::Container); + is($controller.name, 'Controller'); + is($controller.parent, $app); + ok(!$controller.has_services); +} + +{ + my $view = $app.get_sub_container('View'); + isa_ok($view, Bread::Board::Container); + is($view.name, 'View'); + is($view.parent, $app); + ok($view.has_services); + + my $service = $view.get_service('TT'); + does_ok($service, Bread::Board::Service); + is($service.parent, $view); +} + +{ + my $model = $app.get_sub_container('Model'); + isa_ok($model, Bread::Board::Container); + is($model.name, 'Model'); + is($model.parent, $app); + ok($model.has_services); + + my $service = $model.get_service('schema'); + does_ok($service, Bread::Board::Service); + is($service.parent, $model); +} + +done; -- cgit v1.2.3