fixed Bar Controller, tons of bugs everywhere, restructured controller namespace
groditi [Fri, 16 Nov 2007 21:20:55 +0000 (21:20 +0000)]
lib/ComponentUI/Controller/Root.pm
lib/ComponentUI/Controller/TestModel/Bar.pm
lib/ComponentUI/Controller/TestModel/Baz.pm
lib/ComponentUI/Controller/TestModel/Foo.pm
lib/ComponentUI/TestModel.pm
lib/Reaction/UI/CRUDController.pm [deleted file]
lib/Reaction/UI/Controller/Collection.pm [new file with mode: 0644]
lib/Reaction/UI/Controller/Collection/CRUD.pm [new file with mode: 0644]
lib/Reaction/UI/Controller/Root.pm [moved from lib/Reaction/UI/RootController.pm with 92% similarity]
lib/Reaction/UI/ViewPort/GridView/Entity.pm
lib/Reaction/UI/Widget/Field/ChooseOne.pm

index 567cf3b..a4d42ee 100644 (file)
@@ -2,7 +2,7 @@ package ComponentUI::Controller::Root;
 
 use strict;
 use warnings;
-use base 'Reaction::UI::RootController';
+use base 'Reaction::UI::Controller::Root';
 use Reaction::Class;
 
 use aliased 'Reaction::UI::ViewPort';
index f3140ee..f7859b7 100644 (file)
@@ -1,6 +1,6 @@
 package ComponentUI::Controller::TestModel::Bar;
 
-use base 'Reaction::UI::CRUDController';
+use base 'Reaction::UI::Controller::Collection::CRUD';
 use Reaction::Class;
 
 __PACKAGE__->config(
index a49c452..f1d7c8b 100644 (file)
@@ -1,6 +1,6 @@
 package ComponentUI::Controller::TestModel::Baz;
 
-use base 'Reaction::UI::CRUDController';
+use base 'Reaction::UI::Controller::Collection::CRUD';
 use Reaction::Class;
 
 __PACKAGE__->config(
index 3477e0f..cc821c5 100644 (file)
@@ -1,6 +1,6 @@
 package ComponentUI::Controller::TestModel::Foo;
 
-use base 'Reaction::UI::CRUDController';
+use base 'Reaction::UI::Controller::Collection::CRUD';
 use Reaction::Class;
 
 __PACKAGE__->config(
index 2559776..e13c31c 100644 (file)
@@ -11,7 +11,9 @@ $reflector->reflect_schema
   (
    model_class  => __PACKAGE__,
    schema_class => 'RTest::TestDB',
-   sources => [qw/Foo Bar Baz/],
+   sources => [qw/Foo Baz/,
+               [ Bar => {attributes => [[-exclude => 'avatar']] } ], ## for now....
+              ],
   );
 
 
diff --git a/lib/Reaction/UI/CRUDController.pm b/lib/Reaction/UI/CRUDController.pm
deleted file mode 100644 (file)
index 47b4531..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-package Reaction::UI::CRUDController;
-
-use strict;
-use warnings;
-use base 'Reaction::UI::Controller';
-use Reaction::Class;
-
-use aliased 'Reaction::UI::ViewPort::ListView';
-use aliased 'Reaction::UI::ViewPort::ActionForm';
-use aliased 'Reaction::UI::ViewPort::ObjectView';
-
-has 'model_name'      => (isa => 'Str', is => 'rw', required => 1);
-has 'collection_name' => (isa => 'Str', is => 'rw', required => 1);
-
-has action_viewport_map  => (isa => 'HashRef', is => 'rw', lazy_build => 1);
-has action_viewport_args => (isa => 'HashRef', is => 'rw', lazy_build => 1);
-
-sub _build_action_viewport_map {
-  return {
-          list       => ListView,
-          view       => ObjectView,
-          create     => ActionForm,
-          update     => ActionForm,
-          delete     => ActionForm,
-          delete_all => ActionForm,
-         };
-}
-
-sub _build_action_viewport_args {
-  my $self = shift;
-  return { list =>
-           { action_prototypes =>
-             [ { label => 'Create', action => sub {
-                   [ '', 'create',    $_[1]->req->captures ] } },
-               { label => 'Delete all', action => sub {
-                   [ '', 'delete_all', $_[1]->req->captures ] } },
-             ],
-             Entity =>
-             { action_prototypes =>
-               [ { label => 'View', action => sub {
-                     [ '', 'view', [ @{$_[1]->req->captures},   $_[0]->__id ] ] } },
-                 { label => 'Edit', action => sub {
-                     [ '', 'update', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
-                 { label => 'Delete', action => sub {
-                     [ '', 'delete', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
-               ],
-             },
-           },
-         };
-}
-
-sub base :Action :CaptureArgs(0) {
-  my ($self, $c) = @_;
-}
-
-#XXX candidate for futre optimization, should cache reader?
-sub get_collection {
-  my ($self, $c) = @_;
-  my $model = $c->model( $self->model_name );
-  my $attr  = $model->meta->find_attribute_by_name( $self->collection_name );
-  my $reader = $attr->get_read_method;
-  return $model->$reader;
-}
-
-sub get_model_action {
-  my ($self, $c, $name, $target) = @_;
-
-  if ($target->can('action_for')) {
-    return $target->action_for($name, ctx => $c);
-  }
-
-  #can we please kill this already?
-  my $model_name = "Action::${name}".$self->model_name;
-  my $model = $c->model($model_name);
-  confess "no such Model $model_name" unless $model;
-  return $model->new(target_model => $target, ctx => $c);
-}
-
-
-
-sub list :Chained('base') :PathPart('') :Args(0) {
-  my ($self, $c) = @_;
-  $c->forward(basic_page => { collection => $self->get_collection($c) });
-}
-
-sub create :Chained('base') :PathPart('create') :Args(0) {
-  my ($self, $c) = @_;
-  my $vp_args = {
-                 next_action => 'list',
-                 on_apply_callback => sub { $self->after_create_callback($c => @_); },
-                };
-  $c->forward( basic_model_action => $vp_args);
-}
-
-sub delete_all :Chained('base') :PathPart('delete_all') :Args(0) {
-  my ($self, $c) = @_;
-  $c->forward(basic_model_action => { next_action => 'list'});
-}
-
-sub after_create_callback {
-  my ($self, $c, $vp, $result) = @_;
-  return $self->redirect_to
-    ( $c, 'update', [ @{$c->req->captures}, $result->id ] );
-}
-
-
-
-sub object :Chained('base') :PathPart('id') :CaptureArgs(1) {
-  my ($self, $c, $key) = @_;
-  my $object :Stashed = $self->get_collection($c)->find($key);
-  confess "Object? what object?" unless $object; # should be a 404.
-}
-
-sub update :Chained('object') :Args(0) {
-  my ($self, $c) = @_;
-  #this needs a better solution. currently thinking about it
-  my @cap = @{$c->req->captures};
-  pop(@cap); # object id
-  my $vp_args = { next_action => [ $self, 'redirect_to', 'list', \@cap ]};
-  $c->forward(basic_model_action => $vp_args);
-}
-
-sub delete :Chained('object') :Args(0) {
-  my ($self, $c) = @_;
-  #this needs a better solution. currently thinking about it
-  my @cap = @{$c->req->captures};
-  pop(@cap); # object id
-  my $vp_args = { next_action => [ $self, 'redirect_to', 'list', \@cap ]};
-  $c->forward(basic_model_action => $vp_args);
-}
-
-sub view :Chained('object') :Args(0) {
-  my ($self, $c) = @_;
-  my $object :Stashed;
-  $c->forward(basic_page => {object => $object});
-}
-
-
-
-
-sub basic_model_action :Private {
-  my ($self, $c, $vp_args) = @_;
-
-  my $target = exists $c->stash->{object} ?
-    $c->stash->{object} : $self->get_collection($c);
-
-  my $cat_action_name = $c->stack->[-2]->name;
-  my $im_action_name  = join('', (map{ uc } split('_', $cat_action_name)));
-  return $self->push_viewport
-    (
-     $self->action_viewport_map->{$cat_action_name},
-     action => $self->get_model_action($c, $im_action_name, $target),
-     %{ $vp_args || {} },
-     %{ $self->action_viewport_args->{$cat_action_name} || {} },
-    );
-}
-
-sub basic_page : Private {
-    my ($self, $c, $vp_args) = @_;
-    my $action_name = $c->stack->[-2]->name;
-    return $self->push_viewport
-    (
-     $self->action_viewport_map->{$action_name},
-     %{ $vp_args || {} },
-     %{ $self->action_viewport_args->{$action_name} || {} },
-    );
-}
-
-1;
diff --git a/lib/Reaction/UI/Controller/Collection.pm b/lib/Reaction/UI/Controller/Collection.pm
new file mode 100644 (file)
index 0000000..d7d727b
--- /dev/null
@@ -0,0 +1,69 @@
+package Reaction::UI::Controller::Collection;
+
+use strict;
+use warnings;
+use base 'Reaction::UI::Controller';
+use Reaction::Class;
+
+use aliased 'Reaction::UI::ViewPort::ListView';
+use aliased 'Reaction::UI::ViewPort::ObjectView';
+
+has 'model_name'      => (isa => 'Str', is => 'rw', required => 1);
+has 'collection_name' => (isa => 'Str', is => 'rw', required => 1);
+
+has action_viewport_map  => (isa => 'HashRef', is => 'rw', lazy_build => 1);
+has action_viewport_args => (isa => 'HashRef', is => 'rw', lazy_build => 1);
+
+sub _build_action_viewport_map {
+  return {
+          list => ListView,
+          view => ObjectView,
+         };
+}
+
+sub _build_action_viewport_args {
+  return { };
+}
+
+sub base :Action :CaptureArgs(0) {
+  my ($self, $c) = @_;
+}
+
+#XXX candidate for futre optimization, should cache reader?
+sub get_collection {
+  my ($self, $c) = @_;
+  my $model = $c->model( $self->model_name );
+  my $attr  = $model->meta->find_attribute_by_name( $self->collection_name );
+  my $reader = $attr->get_read_method;
+  return $model->$reader;
+}
+
+sub list :Chained('base') :PathPart('') :Args(0) {
+  my ($self, $c) = @_;
+  $c->forward(basic_page => [{ collection => $self->get_collection($c) }]);
+}
+
+sub object :Chained('base') :PathPart('id') :CaptureArgs(1) {
+  my ($self, $c, $key) = @_;
+  my $object :Stashed = $self->get_collection($c)->find($key);
+  confess "Object? what object?" unless $object; # should be a 404.
+}
+
+sub view :Chained('object') :Args(0) {
+  my ($self, $c) = @_;
+  my $object :Stashed;
+  $c->forward(basic_page => [{object => $object}]);
+}
+
+sub basic_page : Private {
+  my ($self, $c, $vp_args) = @_;
+  my $action_name = $c->stack->[-2]->name;
+  return $self->push_viewport
+    (
+     $self->action_viewport_map->{$action_name},
+     %{ $vp_args || {} },
+     %{ $self->action_viewport_args->{$action_name} || {} },
+    );
+}
+
+1;
diff --git a/lib/Reaction/UI/Controller/Collection/CRUD.pm b/lib/Reaction/UI/Controller/Collection/CRUD.pm
new file mode 100644 (file)
index 0000000..8a2dcd0
--- /dev/null
@@ -0,0 +1,111 @@
+package Reaction::UI::Controller::Collection::CRUD;
+
+use strict;
+use warnings;
+use base 'Reaction::UI::Controller::Collection';
+use Reaction::Class;
+
+use aliased 'Reaction::UI::ViewPort::ActionForm';
+
+sub _build_action_viewport_map {
+  my $map = shift->next::method(@_);
+  map{ $map->{$_} = ActionForm } qw/create update delete delete_all/;
+  return $map;
+}
+
+sub _build_action_viewport_args {
+  my $args = shift->next::method(@_);
+  $args->{list} =
+    { action_prototypes =>
+      [ { label => 'Create', action => sub {
+            [ '', 'create',    $_[1]->req->captures ] } },
+        { label => 'Delete all', action => sub {
+            [ '', 'delete_all', $_[1]->req->captures ] } },
+      ],
+      Entity =>
+      { action_prototypes =>
+        [ { label => 'View', action => sub {
+              [ '', 'view', [ @{$_[1]->req->captures},   $_[0]->__id ] ] } },
+          { label => 'Edit', action => sub {
+              [ '', 'update', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
+          { label => 'Delete', action => sub {
+              [ '', 'delete', [ @{$_[1]->req->captures}, $_[0]->__id ] ] } },
+        ],
+      },
+    };
+  return $args;
+}
+
+sub get_model_action {
+  my ($self, $c, $name, $target) = @_;
+
+  if ($target->can('action_for')) {
+    return $target->action_for($name, ctx => $c);
+  }
+
+  #can we please kill this already?
+  my $model_name = "Action::${name}".$self->model_name;
+  my $model = $c->model($model_name);
+  confess "no such Model $model_name" unless $model;
+  return $model->new(target_model => $target, ctx => $c);
+}
+
+sub create :Chained('base') :PathPart('create') :Args(0) {
+  my ($self, $c) = @_;
+  my $vp_args = {
+                 next_action => 'list',
+                 on_apply_callback => sub { $self->after_create_callback($c => @_); },
+                };
+  $c->forward( basic_model_action => [$vp_args]);
+}
+
+sub delete_all :Chained('base') :PathPart('delete_all') :Args(0) {
+  my ($self, $c) = @_;
+  $c->forward(basic_model_action => [{ next_action => 'list'}]);
+}
+
+sub after_create_callback {
+  my ($self, $c, $vp, $result) = @_;
+  return $self->redirect_to
+    ( $c, 'update', [ @{$c->req->captures}, $result->id ] );
+}
+
+sub update :Chained('object') :Args(0) {
+  my ($self, $c) = @_;
+  #this needs a better solution. currently thinking about it
+  my @cap = @{$c->req->captures};
+  pop(@cap); # object id
+  my $vp_args = { next_action => [ $self, 'redirect_to', 'list', \@cap ]};
+  $c->forward(basic_model_action => [$vp_args]);
+}
+
+sub delete :Chained('object') :Args(0) {
+  my ($self, $c) = @_;
+  #this needs a better solution. currently thinking about it
+  my @cap = @{$c->req->captures};
+  pop(@cap); # object id
+  my $vp_args = { next_action => [ $self, 'redirect_to', 'list', \@cap ]};
+  $c->forward(basic_model_action => [$vp_args]);
+}
+
+sub basic_model_action :Private {
+  my ($self, $c, $vp_args) = @_;
+
+  my $target = exists $c->stash->{object} ?
+    $c->stash->{object} : $self->get_collection($c);
+
+  my $cat_action_name = $c->stack->[-2]->name;
+  my $im_action_name  = join('', (map{ ucfirst } split('_', $cat_action_name)));
+  $c->log->debug($cat_action_name);
+  $c->log->debug($self->action_viewport_map->{$cat_action_name});
+  $c->log->debug(keys %{$self->action_viewport_map});
+  return $self->push_viewport
+    (
+     $self->action_viewport_map->{$cat_action_name},
+     action => $self->get_model_action($c, $im_action_name, $target),
+     %{ $vp_args || {} },
+     %{ $self->action_viewport_args->{$cat_action_name} || {} },
+    );
+}
+
+1;
similarity index 92%
rename from lib/Reaction/UI/RootController.pm
rename to lib/Reaction/UI/Controller/Root.pm
index 89f1a0f..2760ec8 100644 (file)
@@ -1,4 +1,4 @@
-package Reaction::UI::RootController;
+package Reaction::UI::Controller::Root;
 
 use base qw/Reaction::UI::Controller/;
 use Reaction::Class;
@@ -33,12 +33,12 @@ sub end :Private {
 
 =head1 NAME
 
-Reaction::UI::RootController - Base component for the Root Controller
+Reaction::UI::Root - Base component for the Root Controller
 
 =head1 SYNOPSIS
 
   package MyApp::Controller::Root;
-  use base 'Reaction::UI::RootController';
+  use base 'Reaction::UI::COntroller::Root';
 
   # Create UI elements:
   $c->stash->{focus_stack}->push_viewport('Reaction::UI::ViewPort');
index 3011f7f..98a55f5 100644 (file)
@@ -173,6 +173,17 @@ class Entity is 'Reaction::UI::ViewPort', which {
             );
     return $self->_build_simple_field(String, $obj, $attr, $args);
   };
+
+  implements _build_fields_for_type_Reaction_InterfaceModel_Object => as {
+    my ($self, $obj, $attr, $args) = @_;
+    $args->{Field}{$attr->name}{layout} = 'value/string'
+      unless( exists  $args->{Field}{$attr->name}         &&
+              exists  $args->{Field}{$attr->name}{layout} &&
+              defined $args->{Field}{$attr->name}{layout}
+            );
+    return $self->_build_simple_field(RelatedObject, $obj, $attr, $args);
+  };
+
 };
 
 1;
index 9754e71..280c9f3 100644 (file)
@@ -5,7 +5,7 @@ use Reaction::UI::WidgetClass;
 class ChooseOne is 'Reaction::UI::Widget::Field', which {
 
   field  renders [ option over func('viewport', 'value_choices') ],
-    { is_required => sub{ $_{viewport}->attribute->required } };
+    { is_required => sub{ $_{viewport}->attribute->is_required } };
 
   option renders [string {"DUMMY"}],
     {