X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FReaction%2FUI%2FController%2FCollection.pm;h=b36d799ce10212d91c145668c01702b68641be77;hb=bd1aa0c203d4e2c70aeb2ced17ad023d2a27dd8f;hp=d907de42613419c11b5848a5ec26d696f970384d;hpb=5c42218310ae1bcf7663c30b45194345c4b7d224;p=catagits%2FReaction.git diff --git a/lib/Reaction/UI/Controller/Collection.pm b/lib/Reaction/UI/Controller/Collection.pm index d907de4..b36d799 100644 --- a/lib/Reaction/UI/Controller/Collection.pm +++ b/lib/Reaction/UI/Controller/Collection.pm @@ -5,7 +5,7 @@ use warnings; use base 'Reaction::UI::Controller'; use Reaction::Class; -use aliased 'Reaction::UI::ViewPort::ListView'; +use aliased 'Reaction::UI::ViewPort::Collection::Grid'; use aliased 'Reaction::UI::ViewPort::Object'; has 'model_name' => (isa => 'Str', is => 'rw', required => 1); @@ -16,7 +16,7 @@ has action_viewport_args => (isa => 'HashRef', is => 'rw', lazy_build => 1); sub _build_action_viewport_map { return { - list => ListView, + list => Grid, view => Object, }; } @@ -25,46 +25,175 @@ 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; + my $collection = $self->collection_name; + if( my $meth = $model->can( $collection ) ){ + return $model->$meth; + } elsif ( my $attr = $model->meta->find_attribute_by_name($collection) ) { + my $reader = $attr->get_read_method; + return $model->$reader; + } + confess "Failed to find collection $collection"; } -sub list :Chained('base') :PathPart('') :Args(0) { +sub base :Action :CaptureArgs(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 = $self->get_collection($c)->find($key); - confess "Object? what object?" unless $object; # should be a 404. + $c->detach("/error_404") unless $object; $c->stash(object => $object); } +sub list :Chained('base') :PathPart('') :Args(0) { + my ($self, $c) = @_; + $self->basic_page($c, { collection => $self->get_collection($c) }); +} + sub view :Chained('object') :Args(0) { my ($self, $c) = @_; - my $object :Stashed; - $c->forward(basic_page => [{model => $object}]); + $self->basic_page($c, { model => $c->stash->{object} }); } -sub basic_page : Private { +sub basic_page { my ($self, $c, $vp_args) = @_; - my $action_name = $c->stack->[-2]->name; - return $self->push_viewport + my $action_name = $c->stack->[-1]->name; + my $vp = $self->action_viewport_map->{$action_name}, + my $args = $self->merge_config_hashes ( - $self->action_viewport_map->{$action_name}, - %{ $vp_args || {} }, - %{ $self->action_viewport_args->{$action_name} || {} }, + $vp_args || {}, + $self->action_viewport_args->{$action_name} || {} , ); + return $self->push_viewport($vp, %$args); } 1; + + +__END__; + +=head1 NAME + +Reaction::UI::Controller + +=head1 DESCRIPTION + +Controller class used to make displaying collections easier. +Inherits from L. + +=head1 ATTRIBUTES + +=head2 model_name + +The name of the model this controller will use as it's data source. Should be a +name that can be passed to C<$C-Emodel> + +=head2 collection_name + +The name of the collection whithin the model that this Controller will be +utilizing. + +=head2 action_viewport_map + +=over 4 + +=item B<_build_action_viewport_map> - Provided builder method, see METHODS + +=item B - Auto generated predicate + +=item B- Auto generated clearer method + +=back + +Read-write lazy building hashref. The keys should match action names in the +Controller and the value should be the ViewPort class that this action should +use. See method C for more info. + +=head action_viewport_args + +Read-write lazy building hashref. Additional ViewPort arguments for the action +named as the key in the controller. See method C for more info. + +=over 4 + +=item B<_build_action_viewport_args> - Provided builder method, see METHODS + +=item B - Auto generated predicate + +=item B- Auto generated clearer method + +=back + +=head1 METHODS + +=head2 get_collection $c + +Returns an instance of the collection this controller uses. + +=head2 _build_action_viewport_map + +Provided builder for C. Returns a hash with two items: + + list => 'Reaction::UI::ViewPort::ListView', + view => 'Reaction::UI::ViewPort::Object', + +=head2 _build_action_viewport_args + +Returns an empty hashref. + +=head2 basic_page $c, \%vp_args + +Accepts two arguments, context, and a hashref of viewport arguments. It will +automatically determine the action name using the catalyst stack and call +C with the ViewPort class name contained in the +C with a set of options determined by merging C<$vp_args> +and the arguments contained in C, if any. + +=head1 ACTIONS + +=head2 base + +Chain link, no-op. + +=head2 list + +Chain link, chained to C. C fetches the collection for the model +and calls C with a single argument, C. + +The default ViewPort for this action is C and +can be changed by altering the C attribute hash. + +=head2 object + +Chain link, chained to C, captures one argument, 'id'. Attempts to find +a single object by searching for a member of the current collection which has a +Primary Key or Unique constraint matching that argument. If the object is found +it is stored in the stash under the C key. + +=head2 view + +Chain link, chained to C. Calls C with one argument, +C, which contains an instance of the object fetched by the C +action link. + +The default ViewPort for this action is C and +can be changed by altering the C attribute hash. + +=SEE ALSO + +L + +=head1 AUTHORS + +See L for authors. + +=head1 LICENSE + +See L for the license. + +=cut