roho has asked for the wisdom of the Perl Monks concerning the following question:
1 package AddressBook::Controller::Search; 2 use strict; 3 use warnings; 4 use Text::CSV_XS; 5 use parent qw(Catalyst::Controller::HTML::FormFu); 6 7 sub search : Global FormConfig { 8 my ($self, $c, $query) = @_; 9 my $form = $c->stash->{form}; 10 11 # Get query from search form 12 if ($form->submitted_and_valid) { 13 $query = $c->request->param('query'); 14 } 15 return unless $query; # No query? We're done 16 $c->stash->{query} = $query; 17 18 # Parse query into tokens 19 my $csv = Text::CSV_XS->new(); 20 $csv->parse($query) or die "Error parsing query"; 21 my @tokens = $csv->fields(); 22 23 # Process query from search form and stash results 24 my $result; 25 if ($form->submitted_and_valid) { 26 if ($c->request->param('domain') eq 'Names') { 27 $result = $c->forward('search_names', \@tokens); 28 $c->stash->{template} = 'search/name_results.tt2'; 29 } else { 30 $result = $c->forward('search_addresses', \@tokens); 31 $c->stash->{template} = 'search/address_results.tt2'; 32 } 33 $c->stash->{result} = $result; 34 my $page = $c->request->param('page'); 35 $page = 1 if ($page !~ /^\d+$/); 36 my $page_result = $result->page($page); 37 $c->stash->{pager} = $page_result->pager; 38 } 39 } 40 41 sub search_names : Private { 42 my ($self, $c, @tokens) = @_; 43 my @people_fields = qw/firstname lastname/; 44 @people_fields = cross(\@people_fields, \@tokens); 45 return $c->model('AddressDB::People')->search(\@people_fields); 46 } 47 48 sub search_addresses : Private { 49 my ($self, $c, @tokens) = @_; 50 my @address_fields = qw/postal phone email location/; 51 @address_fields = cross(\@address_fields, \@tokens); 52 return $c->model('AddressDB::Addresses')->search(\@address_fiel +ds); 53 } 54 55 sub cross { 56 my $columns = shift || []; 57 my $tokens = shift || []; 58 map {s/%/\\%/g} @$tokens; 59 my @result; 60 foreach my $column (@$columns){ 61 push @result, (map +{$column => {-like => "%$_%"}}, @$token +s); 62 } 63 return @result; 64 } 65 66 1;
Previously (pp. 39-40) the book showed how to use sessions
to leave the correct URL in the address bar by using redirect as follows:
  $c->response->redirect($c->uri_for('<URL path>'));
This worked fine for the "edit" and "delete" actions previously in the application, but is not working for "search".
I replaced $c->stash->{template} = '<template-name>'
with $c->flash->{template} = '<template-name>' and
$c->stash->{result} = $result with
$c->flash->{result} = $result, and $c->stash->{pager} with $c->flash->{pager}, which generated the following error message from DBIx::Class:
  
undef error - Can't call method "select" on an undefined value at:
C;/Perl/site/lib/DBIx/Class/ResultSet.pm line 670
1 package AddressBook::Controller::Search; 2 use strict; 3 use warnings; 4 use Text::CSV_XS; 5 use parent qw(Catalyst::Controller::HTML::FormFu); 6 7 sub search : Global FormConfig { 8 my ($self, $c, $query) = @_; 9 my $form = $c->stash->{form}; 10 11 # Get query from search form 12 if ($form->submitted_and_valid) { 13 $query = $c->request->param('query'); 14 } 15 return unless $query; # No query? We're done 16 $c->stash->{query} = $query; 17 18 # Parse query into tokens 19 my $csv = Text::CSV_XS->new(); 20 $csv->parse($query) or die "Error parsing query"; 21 my @tokens = $csv->fields(); 22 23 # Process query from search form and flash results 24 my $result; 25 if ($form->submitted_and_valid) { 26 if ($c->request->param('domain') eq 'Names') { 27 $result = $c->forward('search_names', \@tokens); 28 $c->flash->{template} = 'search/name_results.tt2'; 29 } else { 30 $result = $c->forward('search_addresses', \@tokens); 31 $c->flash->{template} = 'search/address_results.tt2'; 32 } 33 $c->flash->{result} = $result; 34 my $page = $c->request->param('page'); 35 $page = 1 if ($page !~ /^\d+$/); 36 my $page_result = $result->page($page); 37 $c->flash->{pager} = $page_result->pager; 38 if ($c->request->param('domain') eq 'Names') { 39 $c->response->redirect($c->uri_for('name_results/')); 40 } else { 41 $c->response->redirect($c->uri_for('address_results/')) +; 42 } 43 } 44 } 45 46 sub search_names : Private { 47 my ($self, $c, @tokens) = @_; 48 my @people_fields = qw/firstname lastname/; 49 @people_fields = cross(\@people_fields, \@tokens); 50 return $c->model('AddressDB::People')->search(\@people_fields); 51 } 52 53 sub search_addresses : Private { 54 my ($self, $c, @tokens) = @_; 55 my @address_fields = qw/postal phone email location/; 56 @address_fields = cross(\@address_fields, \@tokens); 57 return $c->model('AddressDB::Addresses')->search(\@address_fiel +ds); 58 } 59 60 sub cross { 61 my $columns = shift || []; 62 my $tokens = shift || []; 63 map {s/%/\\%/g} @$tokens; 64 my @result; 65 foreach my $column (@$columns){ 66 push @result, (map +{$column => {-like => "%$_%"}}, @$token +s); 67 } 68 return @result; 69 } 70 71 1;
I changed flash back to stash for {result} and the DBIx::Class error goes away and the correct URL is displayed in the address bar on the search results page, however no search results are displayed.
It almost seems like a catch-22 situation, where stash is needed for {result} to make DBIx::Class work, but flash is needed for {result} to make $c->response->redirect... work.
I tried using BOTH stash and flash but got the same error I received when using flash only.
Any ideas on how this problem might be resolved?
TIA
"Its not how hard you work, its how much you get done."
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Catalyst: stash vs. flash
by ikegami (Patriarch) on Apr 26, 2010 at 05:03 UTC | |
by roho (Bishop) on Apr 26, 2010 at 14:32 UTC |