X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FReaction%2FUI%2FController.pm;h=8ed781f70e8c4ad474b2f7fcb1d8c7973eea3d17;hb=a0ff2c8198d7cfcdefad1cbbaf339bd849a9c2c0;hp=aa1b8bef045763d024567f503d0a3ba0abaab91f;hpb=f1cd5548dac21719deb3412fbc5d8dadb9338cc3;p=catagits%2FReaction.git diff --git a/lib/Reaction/UI/Controller.pm b/lib/Reaction/UI/Controller.pm index aa1b8be..8ed781f 100644 --- a/lib/Reaction/UI/Controller.pm +++ b/lib/Reaction/UI/Controller.pm @@ -1,12 +1,19 @@ package Reaction::UI::Controller; -use base qw( - Catalyst::Controller - Catalyst::Component::ACCEPT_CONTEXT - Reaction::Object -); +use base qw(Catalyst::Controller); # Reaction::Object); use Reaction::Class; +use Scalar::Util 'weaken'; +use namespace::clean -except => [ qw(meta) ]; + +has context => (is => 'ro', isa => 'Object', weak_ref => 1); +with 'Catalyst::Component::InstancePerContext'; + +sub build_per_context_instance { + my ($self, $c, @args) = @_; + my $newself = $self->new($self->_application, {%$self, context => $c, @args}); + return $newself; +} sub push_viewport { my $self = shift; @@ -19,9 +26,7 @@ sub push_viewport { $vp_attr = $vp_attr->[0]; } if (ref($vp_attr) eq 'HASH') { - if (my $conf_class = delete $vp_attr->{class}) { - $class = $conf_class; - } + $class = $vp_attr->{class} if defined $vp_attr->{class}; %args = %{ $self->merge_config_hashes($vp_attr, {@proto_args}) }; } else { $class = $vp_attr; @@ -53,17 +58,17 @@ sub redirect_to { #the confess calls could be changed later to $c->log ? my $action; - if(!ref $to){ - $action = $self->action_for($to); - confess("Failed to locate action ${to} in " . blessed($self)) unless $action; - } - elsif( blessed $to && $to->isa('Catalyst::Action') ){ - $action = $to; - } elsif(ref $action eq 'ARRAY' && @$action == 2){ #is that overkill / too strict? - $action = $c->controller($to->[0])->action_for($to->[1]); - confess("Failed to locate action $to->[1] in $to->[0]" ) unless $action; + my $reftype = ref($to); + if( $reftype eq '' ){ + $action = $self->action_for($to); + confess("Failed to locate action ${to} in " . blessed($self)) unless $action; + } elsif($reftype eq 'ARRAY' && @$to == 2){ #is that overkill / too strict? + $action = $c->controller($to->[0])->action_for($to->[1]); + confess("Failed to locate action $to->[1] in $to->[0]" ) unless $action; + } elsif( blessed $to && $to->isa('Catalyst::Action') ){ + $action = $to; } else{ - confess("Failed to locate action from ${to}"); + confess("Failed to locate action from ${to}"); } $cap ||= $c->req->captures; @@ -73,13 +78,39 @@ sub redirect_to { $c->res->redirect($uri); } +sub make_context_closure { + my($self, $closure) = @_; + my $ctx = $self->context; + weaken($ctx); + return sub { $closure->($ctx, @_) }; +} + 1; __END__; =head1 NAME -Reaction::UI::Controller +Reaction::UI::Controller - Reaction Base Controller Class + +=head1 SYNOPSIS + + package MyApp::Controller::Foo; + use strict; + use warnings; + use parent 'Reaction::UI::Controller'; + + use aliased 'Reaction::UI::ViewPort'; + + sub foo: Chained('/base') Args(0) { + my ($self, $ctx) = @_; + + $ctx->push_viewport(ViewPort, + layout => 'foo', + ); + } + + 1; =head1 DESCRIPTION @@ -151,6 +182,45 @@ controller. $captures and $args default to the current requests $captures and $args if not supplied. +=head2 make_context_closure + +The purpose of this method is to prevent memory leaks. +It weakens the context object, often denoted $c, and passes it as the +first argument to the sub{} that is passed to the make_context_closure method. +In other words, + +=over 4 + +make_context_closure returns sub { $sub_you_gave_it->($weak_c, @_) + +=back + +To further expound up this useful construct consider code written before +make_context_closure was created: + + on_apply_callback => + sub { + $self->after_search( $c, @_ ); + } + ), + +This could be rewritten as: + + on_apply_callback => $self->make_context_closure( + sub { + my $weak_c = shift; + $self->after_search( $weak_c, @_ ); + } + ), + +Or even more succintly: + + on_apply_callback => $self->make_context_closure( + sub { + $self->after_search( @_ ); + } + ), + =head1 AUTHORS See L for authors.