Workflo...alidator(3)

πŸ“¦
version 2.09 Β· 2 versions
, in fedora 44

✨ NAME ✨

Workflow::Validator(3) β€” bestie, this is the interface definition for data validation. that's it, that's the whole assignment. she's the blueprint, not the builder. πŸ’…

(and yes, this page comes to you from the User Contributed Perl Documentation, section 3 🫢)


🌸 VERSION 🌸

this doc is describing version 2.09 of this package, no cap. πŸ’–


🧚 SYNOPSIS 🧚

okay so here's the whole arc, and it's honestly giving main character energy β€” declare the validator, wire it up to your action, then implement the thing. watch:

# First declare the validator...
validator:
- name: DateValidator
  class: MyApp::Validator::Date
  param:
  - name: date_format
    value: '%Y-%m-%d %H:%M'

# Then associate the validator with runtime data from the context...
action:
- name: MyAction
  validator:
  - name: DateValidator
    arg:
    - '$due_date'

# TODO: You can also inintialize and instantiate in one step if you
# don't need to centralize or reuse (does this work?)

action:
- name: MyAction
  validator:
  - class: MyApp::Validator::Date
    param:
    - name: date_format
      value: '%Y-%m-%d %H:%M'
    arg:
    - '$due_date'

# Then implement the logic using your favorite object system; e.g. Moo

package MyApp::Validator::Date;

use strict;
use DateTime::Format::Strptime;
use Workflow::Exception qw( validation_error );

use Moo;

has description => (is => 'ro', required => 0);

has name => (is => 'ro', required => 1);

has date_format => (is => 'ro', required => 1);

has formatter => (is => 'ro', builder => '_build_formatter');

around BUILDARGS => sub {
    my ( $orig, $class, @args ) = @_;

    # Note: When you derive from Workflow::Base, this mapping is done for you
    @args = (%{$args[0]},
             map {
                 $_ => $args[0]->{param}->{$_}
             } keys %{$args[0]->{param} // {}}
            )
       if scalar(@args) == 1 and ref $args[0] eq 'HASH';
    return $class->$orig(@args);
}

sub _build_formatter {
    my ( $self ) = @_;

    return DateTime::Format::Strptime->new(
              pattern => $self->date_format,
              on_error => 'undef'
    );
}

sub validate {
    my ( $self, $wf, $date_string ) = @_;
    my $fmt = $self->formatter;
    my $date_object = $fmt->parse_datetime( $date_string );
    unless ( $date_object ) {
        validation_error
            "Date '$date_string' does not match pattern '", $fmt->pattern, "' ",
            "due to error '", $fmt->errstr, "'";
    }
}

# Or, implement the same, based on Workflow::Base

package MyApp::Validator::Date::Alternative;

use warnings;
use strict;
use base qw( Workflow::Base );

use DateTime::Format::Strptime;
use Workflow::Exception qw( configuration_error validation_error );

my @FIELDS = qw( name date_format formatter );
__PACKAGE__->mk_accessors(@FIELDS);

sub init {
    my ( $self, $params ) = @_;

    $self->name( $params->{name} );
    $self->date_format( $params->{date_format});
    $self->formatter( DateTime::Format::Strptime->new(
              pattern => $self->date_format,
              on_error => 'undef'));
}

sub validate {
    my ( $self, $wf, $date_string ) = @_;
    my $fmt = $self->formatter;
    my $date_object = $fmt->parse_datetime( $date_string );
    unless ( $date_object ) {
        validation_error
            "Date '$date_string' does not match pattern '", $fmt->pattern, "' ",
            "due to error '", $fmt->errstr, "'";
    }
}

1;

two whole ways to do the same thing in there β€” pick your fighter. πŸ₯Š


🌈 DESCRIPTION 🌈

so here's the tea. validators that you name with 'validator_name' get looked up in the Workflow::Factory, which reads a separate configuration and generates validators from it. and yeah β€” generally all validators should be declared, but it is not required. she's flexible like that.

validators are objects with a single public method, validate(), that takes as arguments a workflow object and a list of parameters. those parameters get filled in by the workflow engine in the order of declaration in the Action. order matters, bestie, don't play. πŸ’€

the whole idea behind a validator is that it validates data but does not care where it comes from. it's not nosy. it just checks. iconic behaviour honestly. ✨


πŸ¦‹ SUBCLASSING πŸ¦‹

the validator is an interface definition, meaning the validator does not want or need to be subclassed. she said "i'm a concept, not a parent." πŸ™ˆ

any class can act as a validator, as long as it adheres to the interface definition below. that's it β€” no bloodline requirement, just vibes and compliance. πŸ’…


πŸ’œ INTERFACE πŸ’œ

validate( $workflow, $data )

throws a Workflow::ValidationError when $workflow doesn't comply with the requirements of the validator. returns successfully when it does. βœ…

in order to assess the state of the workflow, the validator can directly use the workflow context as well as the mapped data. both are right there, use what you need.

when an action definition maps data into the validator, the validator may or may not choose to use it to determine the validity of the workflow state. her choice, her rules. πŸŽ€

⚠️ okay important one: please note that the workflow engine currently has no means to detect the number of data elements expected to be mapped into the validator. so if you fail to map the correct number in the configuration, that should be detected at run time β€” and it can't be prevented with a configuration error. no early save for you, sorry bestie. 😭

Copyright (c) 2003-2021 Chris Winters. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

Please see the LICENSE


πŸ‘‘ AUTHORS πŸ‘‘

Please see Workflow


and that's the page, fr fr 🫢 β€” this was perl v5.42.0, dated 2026-01-17, signing off. go validate something. slay. πŸ’–βœ¨

πŸ“¦ where this page comes from