NAME
Form::Factory::Action - Role implemented by actions
VERSION
version 0.022
DESCRIPTION
This is the role implemented by all form actions. Rather than doing so directly, you should use Form::Factory::Processor as demonstrated in the "SYNOPSIS".
SYNOPSIS
package MyApp::Action::Foo;
use Form::Factory::Processor;
has_control bar => (
type => 'text',
);
sub run {
my $self = shift;
# Do something...
}
ATTRIBUTES
All form actions have the following attributes.
form_interface
This is the Form::Factory::Interface that constructed this action. If you need to get at the implementation directly for some reason, here it is. This is mostly used by the action itself when calling the "render" and "consume" methods.
globals
This is a hash of extra parameters to keep with the form. Normally, these are saved with a call to "stash" and recovered with a call to "unstash".
results
This is a Form::Factory::Result::Gathered object that tracks the general success, failure, messages, and output from the execution of this action.
Actions delegate a number of methods to this object. See "RESULTS".
result
This is a Form::Factory::Result::Single used to record general outcome.
Actions delegate a number of methods to this object. See "RESULTS".
features
This is a list of Form::Factory::Feature objects used to modify the object. This will always contain the features that are attached to the class itself. Additional features may be added here.
controls
This is a hash of controls attached to this action. For every has_control
line in the action class, there should be a matching control in this hash.
METHODS
stash
$action->stash($moniker);
Given a $moniker
(a key under which to store the information related to this form), this will stash the form's stashable information under that name using the Form::Factory::Stasher associated with the "form_interface".
The globals, values of controls, and the results are stashed. This allows those values to be recovered across requests or between process calls or whatever the implementation requires.
unstash
$action->unstash($moniker);
Given a $moniker
previously named in a call to "stash", it restores the previously stashed state. This is a no-op if nothing is stashed under this moniker.
clear
This method clears the stashable state of the action.
render
$action->render(%options);
Renders the form using the associated "form_interface". You may specify the following options:
- controls
-
This is a list of control names to render. If not given, all controls will be rendered.
Any other options will be passed on to the "render_control" in Form::Factory::Interface method.
setup_and_render
$self->setup_and_render(%options);
This performs the most common steps to prepare for a render and render:
Unstashes from the given
moniker
.Adds the given
globals
to the globals.Renders the action.
Clears the results.
Stashes what we've done back into the given
moniker
.
render_control
my $control = $action->render_control($name, \%options);
Creates and renders a one time control. This is mostly useful for attaching buttons to a form. The control is not added to the list of controls on the action and will not be processed later.
This method returns the control object that was just rendered.
consume
$action->consume(%options);
This consumes any input from user and places it into the controls of the form. You may pass the following options:
- controls
-
This is a list of names of controls to consume. Any not listed here will not be consumed. If this option is missing, all control values are consumed.
Any additional options will be passed to the "consume_control" in Form::Factory::Interface method call.
consume_control
my $control = $action->consume_control($name, \%options, %params);
Consumes the value of a one time control. This is useful for testing to see if a form submitted using a one-time control has been submitted or not.
This method returns the control object that was consumed.
clean
$action->clean(%options);
Takes the values consumed from the user and cleans them up. For example, if you allow users to type in a phone number, this can be used to clear out any unwanted or incorrect punctuation and format the phone number properly.
This method runs through all the requested Form::Factory::Feature objects in "features" and runs the "clean" in Form::Factory::Feature method for each.
The following options are used:
- controls
-
This is the list of controls to clean. If not given, all features will be run. If given, only the control-features (those implementing Form::Factory::Feature::Role::Control attached to the named controls) will be run. Any form-features or unlisted control-features will not be run.
check
$action->check(%options);
The check
method is responsible for verifying the correctness of the input. It assumes that "clean" has already run.
It runs the "check" in Form::Factory::Feature method of all the selected "features" attached to the action. It also sets the is_valid
flag to true if no errors have been recored yet or to false if they have.
The following options are used:
- controls
-
This is the list of controls to check. If not given, all features will be run. If given, only the control-features (those implementing Form::Factory::Feature::Role::Control attached to the named controls) will be run. Any form-features or unlisted control-features will not be run.
process
$action->process;
This does nothing if the action did not validate.
In the case the action is valid, this will use "set_attributes_from_controls" to copy the control values to the action attributes, run the "pre_process" in Form::Factory::Feature methods for all form-features and control-features, call the "run" method, run the "post_process" in Form::Factory::Feature methods for all form-features and control-features, and set the is_success
flag to true if no errors are recorded or false if there are.
consume_and_clean_and_check_and_process
This is a shortcut for taking all the usual workflow actions in a single call:
$action->consume(@_);
$action->clean;
$action->check
$action->process;
ROLE METHODS
This method must be implemented by any action implementation.
run
This is the method that actually does the work. It takes no arguments and is expected to return nothing. You should draw your input from the action attributes (not the controls) and report your results to "result".
HELPER METHODS
These methods are primarily intended for internal use.
set_attribute_from_control
Given the name of a control, this will copy the current value in the control to the attribute.
set_attributes_from_controls
This method is used by "process" to copy the values out of the controls into the form action attributes. This assumes that such a copy will work because the "clean" and "check" phases should have already run and passed without error.
gather_results
Gathers results for all the associated "controls" and "result" into "results". This is called just before deciding if the action has validated correctly or if the action has succeeded.
RESULTS
Actions are tied closely to Form::Factory::Results. As such, a number of methods are delegated to result classes.
The following methods are delegated to "results" in Form::Factory::Result::Gathered.
- is_valid
- is_success
- is_failure
- is_validated
- is_outcome_known
- all_messages
- regular_messages
- field_messages
- info_messages
- warning_messages
- error_messages
- regular_info_messages
- regular_warning_messages
- regular_error_messages
- field_info_messages
- field_warning_messages
- field_error_messages
- content
These methods are delegated to result in Form::Factory::Result::Single.
- success
- failure
- add_message
- info
- warning
- error
- field_info
- field_warning
- field_error
WORKFLOW
TYPICAL CASE
The action workflow typically goes like this. There are two phases.
PHASE 1: SHOW THE FORM
Phase 1 is responsible for showing the form to the user. This phase might be skipped altogether in situations where automatic processing is taking place where the robot doing the work already knows what inputs are expected for the action. However, typically, you do something like this:
my $action = $interface->new_action('Foo');
$action->unstash('foo');
$action->render;
$action->render_control(button => {
name => 'submit',
label => 'Do It',
});
$action->stash('foo');
This tells the interface that you want to prepare a form object for class "Foo."
The call to "unstash" then pulls in any state saved from the user's prior entry. This will cause any errors that occurred on a previous validation or process execution to show up (assuming that your interface does that work for you). This also means that any previously stashed values entered should reappear in the form so that a failure to save or something won't cause the field information to be lost forever.
The call to "render" causes all of the controls of the form to be rendered for input.
The call to "render_control" causes a button to appear in the form.
The call to "stash" returns the form's stashable information back to the stash, since "unstash" typically removes it.
PHASE 2: PROCESSING THE INPUT
Once the user has submitted the form, you will want to process the input and perform the action. This typically looks like this:
my $action = $interface->new_action('Foo');
$action->unstash('foo');
$action->consume_and_clean_and_check_and_process( request => $q->Vars );
if ($action->is_valid and $action->is_success) {
# Go on to the next thing
}
else {
$action->stash('foo');
# Go render the form again and show the errors
}
We request an instance of the form again and then call "unstash" to recover any stashed setup. We then call the "consume_and_clean_and_check_and_process" method, which will consume all the input. Here we use something that looks like a CGI request for the source of input, but it should be whatever is appropriate to your environment and the Form::Factory::Interface implementation used.
At the end, we check to see if the action checked out and then that the "run" method ran without problems. If so, we can show the success page or the record view or whatever is appropriate after filling this form.
If there are errors, we should perform the rendering action for "PHASE 1: SHOW THE FORM" again after doing a "stash" to make sure the information is ready to be recovered.
VARATIONS
PER-CONTROL CLEANING AND CHECKING
Ajax or GUIs will generally want to give their feedback as early as possible. As such, whenever the user finishes entering a value or the application thinks that validation is needed, the app might perform:
$action->check( controls => [ qw( some_control ) ] );
$action->clean( controls => [ qw( some_control ) ] );
unless ($action->is_valid) {
# Report $action->results->error_messages
}
You will still run the steps above, but can do a check and clean on a subset of controls when you need to do so to give the user early feedback.
AUTHOR
Andrew Sterling Hanenkamp <hanenkamp@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2015 by Qubling Software LLC.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.