[jifty-devel] Action in a link? Without a <form>?

jpollack at gmail.com jpollack at gmail.com
Mon Feb 26 16:31:07 EST 2007


On 2/26/07, Henry Baragar <Henry.Baragar at instantiated.ca> wrote:
> Note that this creates a confirmation pop-up (which we like because we believe
> that a link should not have side effects).  Also, I was not sure if you were
> referring to Jifty actions (not used here) or using a more generic
> definition, when you mentioned "actions".

I do mean Jifty actions, which I like (among other reasons) because I
get CRUD actions for free from my Model definitions.

> My question is:  is there a better way to do this?
>
> > I've hacked together something crude where I tangent to a page which
> > contains $a = new_action; $a->run; jifty->web->return, which works,

You might like the hack that I mentioned earlier.  I use YAML to
serialize the arguments to the action, which is not perfectly robust,
but far from the worst one can do.  There are two templates,
'action_link', and 'do_action'.

do_action:

<%init>
use Jifty::YAML;
my $args = {}; %{$args} = %ARGS;

if (exists ($args->{'args'})) {
  $args->{'args'} =~ s/\,/\n/g;
  $args->{'args'} = YAML::Load ($args->{'args'});
}

if (exists ($args->{'class'})) {
  my $action;
  if (exists ($args->{'args'})) {
    $action = Jifty->web->new_action (class => $args->{'class'},
                                      arguments => $args->{'args'}
                                     );
  } else {
    $action = Jifty->web->new_action (class => $args->{'class'});
  }
  $action->run () if ($action);
}

if (exists ((Jifty->web->caller ())->{'path'})) {
  Jifty->web->return;
} else {
  Jifty->web->goto (url => '/');
}
</%init>

and action_link:

<%args>
$class
$label => $class
$args => undef
</%args>
<span class="<% "action-" . lc ($class) %>">
% use Jifty::YAML;
% my $params = { class => $class };
% if (defined ($args) and ref ($args)) {
%   $params->{'args'} = Jifty::YAML::Dump ($args);
%   $params->{'args'} =~ s/\n/\,/g;
% }
<% Jifty->web->tangent (url => "/do_action",
                        label => $label,
                        parameters => $params) %>
</span>

Then, from any other template, if I wish to have a link which takes an
action, all I have to type is this:

<& /action_link, class => "DeleteFriend", label => "remove?", args =>
{'id' => $friend->id} &>

or the simpler

<& /action_link, class => "Logout", label => "logout?" &>

You might find this somewhat useful as it uses a continuation so that
after the action is run, it returns to the page that contained the
action_link.  Contrast that with needing to specify 'original_page' in
your Dispatcher.

But still... The problem with my solution is that all those redirects
ruin the state on the calling page, in particular the arguments to my
pageregions.  Also, I think there's got to be a better way.
: )

Joshua


More information about the jifty-devel mailing list