Almost there, builds controllers with methods in them...
t0m [Thu, 23 Apr 2009 01:00:37 +0000 (02:00 +0100)]
lib/CatalystX/DynamicComponent.pm
lib/CatalystX/ModelToControllerReflector.pm
lib/CatalystX/ModelsFromConfig.pm

index 8208689..1c0d8ad 100644 (file)
@@ -3,7 +3,7 @@ use Moose::Role;
 use namespace::clean -excpept => 'meta';
 
 sub _setup_dynamic_component {
-    my ($app, $name, $config) = @_;
+    my ($app, $name, $config, $component_method) = @_;
 
     my $appclass = blessed($app) || $app;
     my $type = $name;
@@ -13,17 +13,7 @@ sub _setup_dynamic_component {
     my $meta = Moose->init_meta( for_class => $name );
     $meta->superclasses('Catalyst::' . $type);
 
-    $meta->add_method(
-
-      COMPONENT
-            => sub {
-        my ($component_class_name, $app, $args) = @_;
-
-        my $class = delete $args->{class};
-        Class::MOP::load_class($class);
-
-        $class->new($args);
-    });
+    $meta->add_method( COMPONENT => $component_method );
 
     $meta->make_immutable;
 
index 60c090c..bfa9b93 100644 (file)
@@ -5,9 +5,9 @@ use namespace::clean -except => 'meta';
 with 'CatalystX::DynamicComponent' 
     => { alias => { _setup_dynamic_component => '_setup_dynamic_controller' } };
 
-requires 'setup_components';
+requires 'setup_actionts';
 
-after 'setup_components' => sub { shift->_setup_dynamic_controllers(@_); };
+before 'setup_actions' => sub { shift->_setup_dynamic_controllers(@_); };
 
 sub _setup_dynamic_controllers {
     my ($app) = @_;
@@ -21,10 +21,41 @@ sub _setup_dynamic_controllers {
 sub _reflect_model_to_controller {
     my ( $app, $model_name, $model ) = @_;
 
+    my $class = blessed($app) || $app;
+
     my $controller_name = $model_name;
     $controller_name =~ s/::Model::/::Controller::/;
 
-    $app->_setup_dynamic_controller( $controller_name );
+    my $suffix = $model_name;
+    $suffix =~ s/^.*::Model:://;
+
+    my $controller = $app->_setup_dynamic_controller( $controller_name, {}, sub {
+        shift->next::method(@_); # Just use the default COMPONENT method
+    });
+    my $meta = $controller->meta;
+    $meta->make_mutable; # Dirty, I should build the class, add the methods, then
+                         # last of all make it a component
+
+    my $methods = $model->meta->get_method_map;
+    foreach my $method_name (keys %$methods) {
+        $controller->meta->add_method(
+            # Note need to pass model name, as the method actually comes from
+            # the underlying model class, not the Catalyst shim class we autogenerated.
+            $method_name => $app->generate_reflected_controller_action_method($suffix, $methods->{$method_name})    
+        );
+    }
+    $meta->make_immutable;
+}
+
+sub generate_reflected_controller_action_method {
+    my ( $app, $model, $method ) = @_;
+    my $method_name = $method->name; # Is it worth passing the actual method object here?
+    sub {
+        my ($self, $c, @args) = @_;
+        $c->res->header('X-From-Model', $model);
+        $c->res->header('X-From-Model-Data', $c->model($model)->$method_name(@args));
+        $c->res->body('OK');
+    };
 }
 
 1;
index 8bf1c9b..f765c40 100644 (file)
@@ -21,11 +21,20 @@ sub _setup_dynamic_models {
     my $app_name = blessed($app) || $app;
     my $model_prefix = 'Model::';
 
-    my $model_hash = $app->config || {};
+    my $config = $app->config || {};
     
-    foreach my $model_name ( grep { /^$model_prefix/ } keys %$model_hash ) {
+    foreach my $model_name ( grep { /^$model_prefix/ } keys %$config ) {
         my $model_class_name = $app_name . '::' . $model_name;
-        $app->_setup_dynamic_model( $model_class_name, $model_hash->{$model_name} );
+        
+        $app->_setup_dynamic_model( $model_class_name, $config->{$model_name}, 
+        sub {
+            my ($component_class_name, $app, $args) = @_;
+
+            my $class = delete $args->{class};
+            Class::MOP::load_class($class);
+
+            $class->new($args);
+        });
     }
 }