Define Behavior with actions
Actions are the business logic behind the scenes. In order to use an action you will have to create an action class inside your lib directory of your application. This can get simplified using the jifty utility.
Create an action
Behind an action the logic on how to connect form elements, models and logic is stored. To create an action you simply do:
$ bin/jifty action --name DemoAction
Writing file .../lib/MyFirstApp/Action/DemoAction.pm
Writing file .../t/00-action-DemoAction.t
Extending the default behavior
Every Action is derived from the classes:
ApplicationName::Action- a magically auto-created class that derives fromJifty::ActionJifty::Actionwhich defines the basic behavior of all actions.
Every action should redefine the following methods:
argumentsDEPRECATED - if defined it must return a hash reference to the arguments that the action will understand. The better approach is to define a schema (see below)take_actionwill be executed to run the logic of the action. Depending on the status of the logic run,$self->resulthas to be set to a meaningful status.
Every action may redefine the following methods:
setupwhich is called before validating arguments, may be defined to do some additional initialization of your action. Upon success, this method must return a boolean true value, false otherwise.cleanupis called after the action has run. Currently the return value is not used any more, but to be on the safe side, you should return a boolean result value indicating the status of your work.monikerreturns a string that has some identifying character for the action within a request. The monikers need to be unique inside a request. If no moniker is defined, an auto-generated moniker will be used.
As an autogenerated moniker will change from request to request, there is no way of getting actions to work as intended. Instead, always assign a moniker with a name that is at least unique to the page (better: unique to your application) to the action in order to make things work well.orderis an integer that defines the order of executionsticky_on_failure/sticky_on_successchanges the stickiness of the form fields. By default, only on error, the fields are sticky (keep the entered input), in case of success, the fields are emptied before redraw.
Internally, there is a two stage process to interact with actions:
- First, for all actions on a given page, in the order the actions like to get processed, each action's method
validateis called, which does the following work:- call
check_authorization, immediately returning if no authorization is granted. The default methodcheck_authorizationwhich is defined inJifty::Actionreturns true meaning a grant. - call
setup, immediately returning in case of major errors. The default method "setup" being defined inJifty::Actionjust returns true doing nothing else. - Next, every argument is run through a canonicalization if the field attached to the argument has a canonicalizer-sub attached. This could be useful to uniquely format times, dates, numbers etc to some unique format.
- Finally, every field is validated running a validation for every field. This checks mandatory fields for empty values or runs a validator function that might be assigned to a field.
- call
- Then, as a second pass, again preserving the order, the
runmethod is invoked that does the following (you need not override this method normally):- if there was a validation error, do not continue anymore
- call
take_action, a method that is typically provided by you - call
cleanup, doing some closing housekeeping if necessary
Working with an action
The action's base class (Jifty::Action) defines several methods for your convenience:
argument_value(name, value)allows to get/set argument values of an action.has_argument(name)tells you if an argument has been provided with a value.form_field(name)returns the form field for the given argument. This may be used to hand-craft an input form.form_value(name)returns a displayable value instead of a form field for the given argument.hidden(name, value)renders a hidden form field.ordergets or sets the order in which this action is runresultreturns the result method ????register??? explain more ???render_errorsrenders the errors that occurred, if anybutton??? explain more ???return??? explain more -- continuation chapter ???
Defining a schema
To define the parameters that your action will use (including a form that may get auto-generated) you should define a schema instead of overloading the arguments method.
A schema consists of a grammar according to the following BNF (omitting non-terminals that are self explaining for perl programmers):
schema_definition ::= 'use' 'Jifty::Action' 'schema' '{' parameter* '}' ';'
parameter ::= 'param' param_identifier '=>' param_info [ ',' param_info ]+
param_info ::= 'label' 'is' string
| 'max_length' is number
| 'mandatory' 'is' boolean_number
| 'ajax' ( 'validates' | 'canonicalizes' )
| ( 'ajax_validates' | 'ajax_canonicalizes' ) 'is' boolean_number
| ( 'order' | 'sort_order' ) 'is' number
| ( 'default' | 'default_value' ) 'is' number_or_string
| ( 'valid' | 'valid_values' ) 'are' array_of_values
| ( 'available' | 'available_values' ) 'are' array_of_values
| ( 'render' 'as' | 'render_as' 'is' ) string
| 'autocompleter' 'is' subroutine_reference
| 'validator' 'is' subroutine_reference
| 'constructor' is subroutine_reference
| 'canonicalizer' is subroutine_reference
| 'hints' 'is' string
| 'placeholder' 'is' string
* 'as', 'is' and 'are' are fill-words that may get omitted.
An example of a simple schema that knows about two input-fields looks like this:
use Jifty::Param::Schema;
use Jifty::Action schema {
param firstname =>
label is 'Firstname',
max_length is 50,
is mandatory;
param lastname =>
label is 'Lastname',
max_length is 30,
is mandatory;
};
Testing an action
In the admin console, all actions are listed. By simply clicking on an action, the action is invoked. This of course only makes sense if the action has defined a schema for an input form. This enables you to view the form, see and test the validation of your action.
Using actions in templates
You may use an action for use in a template by simply creating an action in a template:
<%init>
my $action = Jifty->web->new_action(class => 'ActionName');
</%init>
Having done that, the action may be used for creating a form in your template. Using some action inside a form automatically makes the action run during the request processing phase. A simple form could look like this:
<% Jifty->web->form->start %>
<% $action->form_field('fieldname') %>
<% Jifty->web->form->submit( label => 'Save' ) %>
<% Jifty->web->form->end %>
More in that topic can be found in Jifty form management