Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Re: Catalyst::Dispatcher - usage of expand_actions

by stonecolddevin (Parson)
on Aug 26, 2015 at 16:06 UTC ( #1140064=note: print w/replies, xml ) Need Help??

in reply to Catalyst::Dispatcher - usage of expand_actions

Show us all of the code you are working with. There needs to be some context in order to figure out what the problem is.

Also, what version of Catalyst are you using?

Three thousand years of beautiful tradition, from Moses to Sandy Koufax, you're god damn right I'm living in the fucking past

  • Comment on Re: Catalyst::Dispatcher - usage of expand_actions

Replies are listed 'Best First'.
Re^2: Catalyst::Dispatcher - usage of expand_actions
by mkchris (Novice) on Aug 26, 2015 at 16:40 UTC

    Ha okay, will try to post everything relevant without putting too much in that you don't need (I'm a little worried that you'll come back and say my code is totally awful!) Bear in mind I've cut out a lot of the error checking that's irrelevant to this.

    So I have my controllers set up something like this:

    =head2 base Chain base for getting the club ID and checking it. Matches /clubs/* =cut sub base :Chained("/") :PathPart("clubs") :CaptureArgs(1) { my ( $self, $c, $id_or_key ) = @_; # Load the messages $c->load_status_msgs; my $club = $c->model("DB::Club")->find_id_or_url_key( $id_or_key ); if ( defined($club) ) { # Club found, stash it, then stash the name / view URL in the brea +dcrumbs section of our stash $c->stash({ club => $club, breadcrumbs => { object => { label => $club->full_name, link => $c->uri_for_action("/clubs/view", [$club->url_key]) +, }, }, }); } else { # 404 $c->detach( "TopTable::Controller::Root", "default" ); return; } } =head2 view Chained to the base class; all this does is check we're authorised to +view clubs, then the more relevant funcionality is in methods chained + from this. =cut sub view :Chained("base") :PathPart("") :CaptureArgs(0) { my ( $self, $c ) = @_; # Check that we are authorised to view clubs $c->forward( "TopTable::Controller::Users", "check_authorisation", [ +"club_view", "view clubs", 1] ); $c->forward( "TopTable::Controller::Users", "check_authorisation", [ + [ qw( club_edit club_delete team_view team_create ) ], "edit clubs", + 0] ); } =head2 Get and stash the current season (or last complete one if it doesn't e +xist) for the team view page. End of chain for /clubs/* =cut =head2 Get and stash the current season (or last complete one if it doesn't e +xist) for the team view page. End of chain for /clubs/* =cut sub view_current_season :Chained("view") :PathPart("") :Args(0) { my ( $self, $c ) = @_; my $club = $c->stash->{club}; # Try to find the current season (or the last completed season if th +ere is no current season) my $season = $c->model("DB::Season")->get_current; # More season stuff # Finalise the view routine $c->detach("view_finalise"); } =head2 view_specific_season View a club only with teams for a specific season. Matches /clubs/*/s +easons/* (End of chain) =cut sub view_specific_season :Chained("view") :PathPart("seasons") :Args(1 +) { my ( $self, $c, $season_id_or_url_key ) = @_; my $club = $c->stash->{club}; # Validate the passed season ID my $season = $c->model("DB::Season")->find_id_or_url_key( $season_id +_or_url_key ); if ( defined($season) ) { # More season stuff # Append the season on to the object for breadcrumbs - this is for + using in sprintf for our text labels $c->stash->{breadcrumbs}{replace_text} = $season->name; } # Finalise the view routine $c->detach("view_finalise"); } sub view_finalise :Private { # Irrelevant to this }

    My breadcrumbs code is:

    # Get the action for the current request and join it on to the names +pace (unless they match, as that means we'll get multiples where we d +on't want it; if the action has a slash in it, we won't join either) my $action = $c->request->action; $action = join("/", $c->namespace, $action) unless $action eq $c-> +namespace or $action =~ m#/#; my @paths = split("/", $action); # This array will hold the breadcrumbs bits in reverse order (we w +ill reverse it when we stash it) my @breadcrumbs = (); my $i = 0; # Counter to tell if we're on the first bit - if we are +, don't link it, as that's the current page while( my $label = pop(@paths) ) { # Skip if we're hiding indices and this is an index next if $label eq "index" and $c->config->{breadcrumbs}{hide_ind +ex}; # The path is all of the @path elements we haven't popped off so + far, plus the current path elemtn (currently in $label) # joined with slashes. my $path = join( "/", @paths, $label ); # Build the label $label = $c->forward( "breadcrumbs_label_for", [$path, $label] ) +; # Now that we have the label for this path, we can get rid of th +e path if this is the first iteration, so we don't link to it $path = "" unless $i; # Push the path and label on to our breadcrumbs array if we have + a label (if it's blank, assume we don't want to display it) push(@breadcrumbs, { path => $path, label => $label, }) if $label; unless ( $i ) { # We need to set up the object after the first iteration so th +at we can have something like 'path > object > action (view, edit, et +c)' if ( exists( $c->stash->{breadcrumbs}{object} ) ) { my $object = $c->stash->{breadcrumbs}{object}; # Check if we have a link and we're not currrently viewing t +he object (no point linking the object if we're already viewing it) if ( exists( $object->{link} ) and $c->request->action !~ /( +view|view_current_season|view_specific_season)$/ ) { # Push the path and label on to our breadcrumbs array push(@breadcrumbs, { path => $object->{link}, label => $object->{label}, }); } else { # Push label only on to our breadcrumbs array push(@breadcrumbs, { label => $object->{label}, }); } } } $i++; # Increment the counter } # Add the home element if we need unless ( $c->config->{breadcrumbs}{hide_home} ) { my $label = $c->forward( "breadcrumbs_label_for", [qw( / home ) +]); push(@breadcrumbs, { path => "/", label => $label }); } =head2 breadcrumbs_label_for Generate labels for specific paths in the breadcrumbs. =cut breadcrumbs_label_for sub breadcrumbs_label_for :Private { my ( $self, $c, $path, $label ) = @_; # If we have a customised label for this path, return it if ( exists( $c->config->{breadcrumbs}{labels}{$path} ) ) { if ( exists( $c->stash->{breadcrumbs}{replace_text} ) ) { # Replacement text, sprintf it # First check if the replacement text is an array, if not, make +it one - this makes it easier to pass in both and not care which is w +hich from now on $c->stash->{breadcrumbs}{replace_text} = [ $c->stash->{breadcrum +bs}{replace_text} ] if ref( $c->stash->{breadcrumbs}{replace_text} ) +ne "ARRAY"; # Now return the sprintf'd version of the label return sprintf( $c->config->{breadcrumbs}{labels}{$path}, @{ $c- +>stash->{breadcrumbs}{replace_text} } ); } else { # No replacement text, just return it return $c->config->{breadcrumbs}{labels}{$path}; } } # If there's no label specified, we use the path. Replace underscor +es with spaces and convert the first following character to uppercase $label =~ s/_(.)/" " . uc($1)/eg; # Return the value with the first character converted to upper-case +(unless we've specified all lower-case) return !$c->config->{breadcrumbs}{lowercase} ? ucfirst($label) : lc( +$label); }

    Hope all this makes sense - genuinely a little worried about showing my code to genuine Perl gurus...! Eventually I think I want to get to something like this:

    controller > object (looked up from base method) > action > 'Seasons' > season
    controller > object > action

    My plan was to split the action up into its individual parts and hopefully do it that way, but I'm getting the previously stated error when I try and do this.

      Okay, so now narrow down the code to figure out what exactly isn't working. What changed from when it was working? Start adding log statements to major parts of the breadcrumbs code, $c->log->debug("GOT $wherever_in_your_breadcrumbs_code"), and figure out at which point they aren't showing up.

      If it's a compilation error, and not a runtime error, do the exact opposite and remove all of your code, and start slowly adding in bits that compile, until you get to a point where you see your error. At that point, you'll have narrowed down your culprit and either have an idea of what's going on or be able to come back here with an isolated piece of code that's failing

      By the way, don't worry about bad code, the only way to learn is to swallow your pride and lay everything out and look at it without attachment.

      Three thousand years of beautiful tradition, from Moses to Sandy Koufax, you're god damn right I'm living in the fucking past

        Got it - thank you for your patience, I was indeed being silly and I should have been using $c->action not $c->request->action

        I'm not against learning things by the way, in fact I enjoy it (especially Perl), but you lot know your stuff and I find that a little intimidating!

A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1140064]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (1)
As of 2021-04-11 07:48 GMT
Find Nodes?
    Voting Booth?

    No recent polls found