NAME¶
Jifty::Action - The ability to Do Things in the framework
SYNOPSIS¶
package MyApp::Action::Foo;
use Jifty::Param::Schema;
use Jifty::Action schema {
param bar =>
type is 'checkbox',
label is 'Want Bar?',
hints is 'Bar is this cool thing that you really want.',
default is 0;
};
sub take_action {
...
}
1;
DESCRIPTION¶
"Jifty::Action" is the superclass for all actions in Jifty. Action
classes form the meat of the Jifty framework; they control how form elements
interact with the underlying model.
See also Jifty::Action::Record for data-oriented actions, Jifty::Result for how
to return values from actions.
See Jifty::Param::Schema for more details on the declarative syntax.
See Jifty::Manual::Actions for examples of using actions.
COMMON METHODS¶
These common methods provide the basic guts for the action.
new¶
Do not call this directly; always go through
"Jifty->web->new_action"!
This method constructs a new action. Subclasses who need do custom
initialization should start with:
my $class = shift;
my $self = $class->SUPER::new(@_)
The arguments that this will be called with include:
Arguments
- moniker
- The moniker of the action. Defaults to an autogenerated
moniker.
- order
- An integer that determines the ordering of the action's
execution. Lower numbers occur before higher numbers. Defaults to 0.
- arguments
- A hash reference of default values for the arguments of the
action. Defaults to none.
- sticky_on_failure
- A boolean value that determines if the form fields are
sticky when the action fails. Defaults to true.
- sticky_on_success
- A boolean value that determines if the form fields are
sticky when the action succeeds. Defaults to false.
_generate_moniker¶
Construct a moniker for a new (or soon-to-be-constructed) action that did not
have an explicit moniker specified. The algorithm is simple: We snapshot the
call stack, prefix it with the action class, and then append it with an
per-request autoincrement counter in case the same class/stack is encountered
twice, which can happen if the programmer placed a "new_action" call
inside a loop.
Monikers generated this way are guaranteed to work across requests.
arguments¶
Note: this API is now deprecated in favour of the declarative syntax
offered by Jifty::Param::Schema.
This method, along with "take_action", is the most commonly overridden
method. It should return a hash which describes the arguments this action
takes:
{
argument_name => {label => "properties go in this hash"},
another_argument => {mandatory => 1}
}
Each argument listed in the hash will be turned into a Jifty::Web::Form::Field
object. For each argument, the hash that describes it is used to set up the
Jifty::Web::Form::Field object by calling the keys as methods with the values
as arguments. That is, in the above example, Jifty will run code similar to
the following:
# For 'argument_name'
$f = Jifty::Web::Form::Field->new;
$f->name( "argument_name" );
$f->label( "Properties go in this hash" );
If an action has parameters that
must be passed to it to execute, these
should have the constructor property set. This is separate from the mandatory
property, which deal with requiring that the user enter a value for that
field.
run¶
This routine, unsurprisingly, actually runs the action.
If the result of the action is currently a success (validation did not fail),
"run" calls "take_action", and finally
"cleanup".
If you're writing your own actions, you probably want to override
"take_action" instead.
validate¶
Checks authorization with "check_authorization", calls
"/setup", canonicalizes and validates each argument that was
submitted, but doesn't actually call "take_action".
The outcome of all of this is stored on the "result" of the action.
check_authorization¶
Returns true if whoever invoked this action is authorized to perform this
action.
By default, always returns true.
setup¶
"setup" is expected to return a true value, or "run" will
skip all other actions.
By default, does nothing.
take_action¶
Do whatever the action is supposed to do. This and "arguments" are the
most commonly overridden methods.
By default, does nothing.
The return value from this method is NOT returned. (Instead, you should be using
the "result" object to store a result).
cleanup¶
Perform any action-specific cleanup. By default, does nothing.
Runs after "take_action" -- whether or not "take_action"
returns success.
moniker¶
Returns the moniker for this action.
argument_value ARGUMENT [VALUE]¶
Returns the value from the argument with the given name, for this action. If
VALUE is provided, sets the value.
has_argument ARGUMENT¶
Returns true if the action has been provided with an value for the given
argument, including a default_value, and false if none was ever passed in.
Returns a Jifty::Web::Form::Field object for this argument. If there is no entry
in the "arguments" hash that matches the given "ARGUMENT",
returns "undef".
Returns a Jifty::Web::Form::Field object that renders a display value instead of
an editable widget for this argument. If there is no entry in the
"arguments" hash that matches the given "ARGUMENT",
returns "undef".
hidden ARGUMENT VALUE¶
A shortcut for specifying a form field "ARGUMENT" which should render
as a hidden form field, with the default value "VALUE".
order [INTEGER]¶
Gets or sets the order that the action will be run in. This should be an
integer, with lower numbers being run first. Defaults to zero.
result [RESULT]¶
Returns the Jifty::Result method associated with this action. If an action with
the same moniker existed in the
last request, then this contains the
results of that action.
register¶
Registers this action as being present, by outputting a snippet of HTML. This
expects that an HTML form has already been opened. Note that this is not a
guarantee that the action will be run, even if the form is submitted. See
Jifty::Request for the definition of "active" actions.
Normally, "new_action" in Jifty::Web takes care of calling this when
it is needed.
render_errors¶
Render any the "error" in Jifty::Result of this action, if any, as
HTML. Returns nothing.
Create and render a button. It functions nearly identically like
"link" in Jifty::Web, except it takes "arguments" in
addition to "parameters", and defaults to submitting this
Jifty::Action. Returns nothing.
Recommended reading: Jifty::Web::Form::Element, where most of the cool options
to button and other things of its ilk are documented.
return PARAMHASH
Creates and renders a button, like "button", which additionally
defaults to calling the current continuation.
Takes an additional argument, "to", which can specify a default path
to return to if there is no current continuation.
NAMING METHODS¶
These methods return the names of HTML form elements related to this action.
register_name¶
Returns the name of the "registration" query argument for this action
in a web form.
Turn one of this action's arguments into a fully qualified name; takes the name
of the field as an argument.
Turn one of this action's arguments into a fully qualified "fallback"
name; takes the name of the field as an argument.
This is specifically to support checkboxes, which only show up in the query
string if they are checked. Jifty creates a checkbox with the value of
form_field_name as its name and a value of 1, and a hidden input with the
value of fallback_form_field_name as its name and a value of 0; using this
information, Jifty::Request can both determine if the checkbox was present at
all in the form, as well as its true value.
error_div_id ARGUMENT¶
Turn one of this action's arguments into the id for the div in which its errors
live; takes name of the field as an argument.
warning_div_id ARGUMENT¶
Turn one of this action's arguments into the id for the div in which its
warnings live; takes name of the field as an argument.
canonicalization_note_div_id ARGUMENT¶
Turn one of this action's arguments into the id for the div in which its
canonicalization notes live; takes name of the field as an argument.
VALIDATION METHODS¶
argument_names¶
Returns the list of argument names. This information is extracted from
"arguments".
_canonicalize_arguments¶
Canonicalizes each of the arguments that this action knows about.
This is done by calling "_canonicalize_argument" for each field
described by "arguments".
_canonicalize_argument ARGUMENT¶
Canonicalizes the value of an argument. If the argument has an attribute named
canonicalizer, call the subroutine reference that attribute points
points to.
If it doesn't have a
canonicalizer attribute, but the action has a
"canonicalize_
ARGUMENT" function, also invoke that function.
If neither of those are true, by default canonicalize dates using
_canonicalize_date
Note that it is possible that a canonicalizer will be called multiple times on
the same field -- canonicalizers should be careful to do nothing to
already-canonicalized data.
_canonicalize_date DATE¶
Parses and returns the date using Jifty::DateTime::new_from_string.
_validate_arguments¶
Validates the form fields. This is done by calling
"_validate_argument" for each field described by
"arguments"
_validate_argument ARGUMENT¶
Validate your form fields. If the field "ARGUMENT" is mandatory,
checks for a value. If the field has an attribute named
validator, call
the subroutine reference validator points to.
If the action doesn't have an explicit
validator attribute, but does have
a "validate_
ARGUMENT" function, invoke that function.
Returns a list of extra arguments to pass to validators. By default, an empty
hash reference, but subclasses can override it to pass, say, a better
"for".
Returns a list of extra arguments to pass to canonicalizers. By default, an
empty hash reference, but subclasses can override it to pass, say, a better
"for".
Returns a list of extra arguments to pass to autocompleters. By default, an
empty hash reference, but subclasses can override it to pass, say, a better
"for".
_autocomplete_argument ARGUMENT¶
Get back a list of possible completions for "ARGUMENT". The list
should either be a list of scalar values or a list of hash references. Each
hash reference must have a key named "value". There can also
additionally be a key named "label" which, if present, will be used
as the user visible label. If "label" is not present then the
contents of "value" will be used for the label.
If the field has an attribute named
autocompleter, call the subroutine
reference
autocompleter points to.
If the field doesn't have an explicit
autocompleter attribute, but does
have a "autocomplete_
ARGUMENT" function, invoke that
function.
valid_values ARGUMENT¶
Given an parameter name, returns the list of valid values for it, based on its
"valid_values" field.
This method returns a hash reference with a "display" field for the
string to display for the value, and a "value" field for the value
to actually send to the server.
(Avoid using this -- this is not the appropriate place for this logic to be!)
available_values ARGUMENT¶
Just like valid_values, but if our action has a set of available recommended
values, returns that instead. (We use this to differentiate between a list of
acceptable values and a list of suggested values)
validation_error ARGUMENT => ERROR TEXT, [OPTIONS]¶
Used to report an error during validation. Inside a validator you should write:
return $self->validation_error( $field => "error");
..where $field is the name of the argument which is at fault. Any extra
"OPTIONS" are passed through to "field_error" in
Jifty::Result.
validation_warning ARGUMENT => WARNING TEXT, [OPTIONS]¶
Used to report a warning during validation. Inside a validator you should write:
return $self->validation_warning( $field => _("warning"));
..where $field is the name of the argument which is at fault. Any extra
"OPTIONS" are passed through to "field_warning" in
Jifty::Result.
validation_ok ARGUMENT, [OPTIONS]¶
Used to report that a field
does validate. Inside a validator you should
write:
return $self->validation_ok($field);
Any extra "OPTIONS" are passed through to "field_warning" in
Jifty::Result and "field_error" in Jifty::Result when unsetting
them.
canonicalization_note ARGUMENT => NOTE¶
Used to send an informational message to the user from the canonicalizer. Inside
a canonicalizer you can write:
$self->canonicalization_note( $field => _("I changed $field for you"));
..where $field is the name of the argument which the canonicalizer is processing
deny REASON¶
When access to an action is denied by Jifty::API::is_allowed the request handler
calls this with a message.
This should mark the action as failed and store the message but may also want to
do other things (such as providing a nicer message or logging somewhere other
than the jifty logs)
CUSTOMIZATION¶
Canonicalization¶
If you wish to have the data in a field normalized into a particular format
(such as changing a date into "YYYY-MM-DD" format, adding commas to
numbers, capitalizing words, or whatever you need) you can do so using a
canonicalizer.
This is just a method titled "canonicalize_FIELD" where
"FIELD" is the name of the field be normalized. Here is an example:
sub canonicalize_foo {
my ($self, $value, $other, $metadata) = @_;
# do something to canonicalize the value
my $normal_form = lc($value) . '-' . $other->{other_field};
$normal_form .= '-update' if $metadata->{for} eq 'update';
return $normal_form;
}
The first parameter to your canonicalizer will be the value to be canonicalized.
The next will be a hash reference of all the parameters submitted with this
canonicalization, so you can be smarter. Finally, the third parameter is a
hash reference of other metadata, such as "for", whose value will be
"create" or "update".
While doing this you might also want to call the
"canonicalization_note" to inform the client of the modification:
my $normal_form = lc($value);
$self->canonicalization_note(
foo => _('Foo values are always in lowercase.'));
If the "foo" field has "ajax canoncalizes" set in the action
schema, then this process will be performed automatically as the form is being
filled without reloading the page.
Validation¶
If a value must follow a certain format, you can provide a validation method for
fields to make sure that no value enters the database until it is in a valid
form.
A validation method is one named "validate_FIELD" where
"FIELD" is the name of the field being checked. Here is an example:
sub validate_foo {
my ($self, $value, $other, $metadata) = @_;
# Check for uppercase letters
if ($value =~ /\p{Lu}/) {
return $self->validation_warning(
foo => _("Foo cannot contain uppercase letters."));
}
# Check for -, *, +, and ?
elsif ($value =~ /[\-\*\+\?]/) {
return $self->validation_error(
foo => _("Foo cannot contain -, *, +, or ?."));
}
return 1;
}
Here the "foo" field should not contain uppercase letters and must not
contain the characters '-', '*', '+', or '?'. You can use
"validation_error" and "validation_warning" to return the
results of your validation to the user or simply return 1 to indicate a valid
value.
Note that the parameters are the same as in "Canonicalization".
If you just have a list of valid values, you may want to use the
"valid_values" schema parameter to perform this task instead.
Autocompletion¶
Autocompletion provides a way of suggesting choices to the client based upon
partial data entry. This doesn't necessarily force the client to use one of
the choices given but gives hints in an application specific way.
To create an autocompletion field, you implement a method named
"autocomplete_FIELD" where "FIELD" is the field to
autocomplete. This is generally done with fields rendered as 'Text'. Here is
an example:
sub autocomplete_foo {
my ($self, $value) = @_;
# Be careful to validate your input! You don't want a malicious user
# hacking your system.
my ($match_value) = $value =~ /^(\w+)$/;
my $foos = MyApp::Model::FooCollection->new;
$foos->limit(
column => 'name',
operator => 'LIKE',
value => '%$value%',
);
return map { $_->name } @{ $foos->items_array_ref };
}
In this example, the "foo" field is autocompleted from names matched
from the "MyApp::Model::Foo" table. The match, in this case, matches
any substring found in the database. I could have matched any item that starts
with the string, ends with the string, matches other fields than the one
returned, etc. It's up to you to decide.
Note also that I have untainted the value coming in to make sure a malicious
user doesn't get anyway. You should always perform a check like this when data
is coming in from an outside source.
If you need a more complicated solution, you can return the autocompletion
values as a list of hash references containing the keys "value" and
(optionally) "label":
return map { { value => $_->name, label => $_->label } }
@{ $foos->items_array_ref };
In this case, the labels will be shown to the client, but the selected value
would be returned to your application.
SEE ALSO¶
Jifty, Jifty::API, Jifty::Action::Record, Jifty::Result, Jifty::Param::Schema,
Jifty::Manual::Actions
LICENSE¶
Jifty is Copyright 2005-2010 Best Practical Solutions, LLC. Jifty is distributed
under the same terms as Perl itself.