Badger
view release on metacpan or search on metacpan
lib/Badger/Data/Facet/Class.pm view on Meta::CPAN
use Carp;
use Badger::Data::Facets;
use Badger::Class
version => 0.01,
debug => 0,
uber => 'Badger::Class',
utils => 'camel_case',
constants => 'DELIMITER ARRAY',
constant => {
FACETS => 'Badger::Data::Facets',
FACET => 'Badger::Data::Facet',
},
hooks => {
type => \&type,
args => \&args,
opts => \&opts,
};
sub type {
my ($self, $type) = @_;
my $facet = $self->FACETS->prototype->find($type)
|| croak "Invalid facet type: $type\n";
$self->base($facet);
}
sub args {
my ($self, $args) = @_;
$args = [ split(DELIMITER, $args) ]
unless ref $args eq ARRAY;
lib/Badger/Data/Type.pm view on Meta::CPAN
import => 'CLASS',
accessors => 'base namespace facets',
constants => 'CODE DOT',
as_text => 'name',
is_true => 1,
constant => {
type => '',
simple => 0,
complex => 0,
# CLAUSES => 'Badger::Data::Clauses',
FACETS => 'Badger::Data::Facets',
},
alias => {
init => \&init_type,
};
use Badger::Debug ':dump';
our @PARAMS = qw( base name namespace );
sub init_type {
my ($self, $config) = @_;
# copy in basic parameters
@$self{ @PARAMS } = @$config{ @PARAMS };
# constraint the type with any validation facets defined
$self->constrain(
$self->class->list_vars( FACETS => $config->{ facets } )
);
return $self;
}
sub name {
my $self = shift;
return $self->{ name } ||= do {
my $pkg = ref $self || $self;
my $base = CLASS;
$pkg =~ s/${base}:://g;
$pkg =~ s/::/./g;
$pkg;
};
}
sub constrain {
my ($self, @args) = @_;
my $FACETS = $self->FACETS;
my $facets = $self->{ facets } ||= [ ];
my $type = $self->type;
my ($name, $value);
$self->debug("preparing facets: ", $self->dump_data($facets)) if DEBUG;
while (@args) {
$name = shift(@args);
$self->debug("preparing facet: $name") if DEBUG;
push(
@$facets,
ref $name eq CODE
? $name
: $FACETS->facet(
# prepend the basic type (e.g. length => text.length)
# unless type and facet are the same (e.g. text => text)
($type eq $name) ? $type : ($type ? $type.DOT.$name : $name),
shift(@args)
)
);
}
$self->debug("constrained type with facets: ", $self->dump_data($facets), "\n")
if DEBUG;
lib/Badger/Data/Type/Class.pm view on Meta::CPAN
package Badger::Data::Type::Class;
use Badger::Debug ':dump';
use Badger::Class
version => 0.01,
debug => 0,
uber => 'Badger::Class',
# words => 'FACETS',
constants => 'ARRAY DELIMITER',
hooks => {
type => \&type,
size => \&size,
facets => \&facets,
};
sub type {
my ($self, $type) = @_;
lib/Badger/Data/Type/Class.pm view on Meta::CPAN
sub size {
my ($self, $size) = @_;
$self->debug("set size to $size") if DEBUG;
$self->method( size => $size );
}
sub facets {
my ($self, $facets) = @_;
my $current = $self->var_default( FACETS => [ ] );
foreach ($facets, $current) {
$_ = [ split DELIMITER ]
unless ref eq ARRAY;
}
push(@$current, @$facets);
$self->debug("merged facets are ", $self->dump_data($facets)) if DEBUG;
$self->var( FACETS => $current );
}
1;
=head1 NAME
Badger::Data::Type::Class - metaprogramming module for data type classes
=head1 SYNOPSIS
t/data/facets.t view on Meta::CPAN
#========================================================================
use lib qw( ./lib ../lib ../../lib );
use Badger::Test
tests => 1,
debug => 'Badger::Data::Type::Simple',
args => \@ARGV;
use Badger::Data::Facets;
use constant FACETS => 'Badger::Data::Facets';
pass('loaded Badger::Data::Facets');
t/data/list_facets.t view on Meta::CPAN
#use Badger::Debug
# modules => 'Badger::Factory';
use Badger::Test
tests => 20,
debug => 'Badger::Data::Facet::List',
args => \@ARGV;
use Badger::Data::Facets;
use constant FACETS => 'Badger::Data::Facets';
#-----------------------------------------------------------------------
# size
#-----------------------------------------------------------------------
my $size = FACETS->facet( 'list.size' => 23 );
ok( $size, 'got size facet from number' );
is( $size->size, 23, 'got size facet with value 23' );
$size = FACETS->facet( 'list.size' => { size => 6 } );
ok( $size, 'got size facet from hash ref' );
is( $size->size, 6, 'got size facet with value 6' );
ok( $size->validate([1..6]), 'list is 6 element long' );
ok( ! $size->try( validate => [1..5] ), 'list is only 5 elements long' );
is( $size->reason->type,
'data.facet.list.size',
'got short size error message'
);
is( $size->reason->info,
'List should have 6 elements (got 5)',
'got short list error message'
);
#-----------------------------------------------------------------------
# min_size
#-----------------------------------------------------------------------
$size = FACETS->facet( 'list.min_size' => 3 );
ok( $size, 'got list.min_size facet' );
$size = FACETS->facet( list_min_size => { min_size => 3 } );
ok( $size, 'got list_min_size facet' );
ok( ! $size->try( validate => [1] ), 'min size fail on 1 list element' );
is( $size->reason->info, 'List should have at least 3 elements (got 1)', 'min size list reason' );
ok( $size->validate([10,20,30]), 'min size on 3 list elements' );
ok( $size->validate([11,21,31,41,51,61]), 'min size on 6 list elements' );
#-----------------------------------------------------------------------
# max_size
#-----------------------------------------------------------------------
$size = FACETS->facet( 'list.max_size' => 3 );
ok( $size, 'got list.max_size facet' );
$size = FACETS->facet( list_max_size => { max_size => 3 } );
ok( $size, 'got list_max_size facet' );
ok( ! $size->try( validate => [1,2,3,4] ), 'max size fail on 4 list elements' );
is( $size->reason->info, 'List should have at most 3 elements (got 4)', 'max size list reason' );
ok( $size->validate([10,20,30]), 'max size on 3 list elements' );
ok( $size->validate([11,21]), 'max size on 2 list elements' );
__END__
#-----------------------------------------------------------------------
# pattern
#-----------------------------------------------------------------------
my $pattern = FACETS->facet( pattern => '^\w+$' );
ok( $pattern, 'got pattern facet' );
ok( ! $pattern->try( validate => 'Hello World!' ), 'pattern fail on 2 words' );
is( $pattern->reason->info, 'Text does not match pattern: ^\w+$', 'pattern fail reason' );
ok( $pattern->validate('foo'), 'pattern match on foo' );
#-----------------------------------------------------------------------
# any
#-----------------------------------------------------------------------
my $any = FACETS->facet( any => ['foo', 'bar'] );
ok( $any, 'got any facet' );
ok( ! $any->try( validate => 'baz' ), 'any fail on baz' );
is( $any->reason->info, 'Text does not match any of the permitted values: baz', 'any fail reason' );
ok( $any->validate('foo'), 'any match on foo' );
#-----------------------------------------------------------------------
# whitespace
#-----------------------------------------------------------------------
my $fold = FACETS->facet( whitespace => 'fold' );
ok( $fold, 'got whitespace folding facet' );
my $text = $fold->validate("Hello\nWorld!");
is( $text, 'Hello World!', 'folded whitespace' );
my $collapse = FACETS->facet( whitespace => 'collapse' );
ok( $collapse, 'got whitespace collapsing facet' );
$text = $collapse->validate(" \n\nHello\n\n\nBadger!\n\n\ ");
is( $text, 'Hello Badger!', 'collapsed whitespace' );
t/data/text_facets.t view on Meta::CPAN
#use Badger::Debug
# modules => 'Badger::Factory';
use Badger::Test
tests => 30,
debug => 'Badger::Data::Facet::Text',
args => \@ARGV;
use Badger::Data::Facets;
use constant FACETS => 'Badger::Data::Facets';
#-----------------------------------------------------------------------
# length
#-----------------------------------------------------------------------
my $length = FACETS->facet( 'text.length' => 23 );
ok( $length, 'got text.length facet from number' );
is( $length->length, 23, 'got length facet with value 23' );
$length = FACETS->facet( text_length => { length => 6 } );
ok( $length, 'got text_length facet from hash ref' );
is( $length->length, 6, 'got length facet with value 6' );
my $text = 'abcdef';
ok( $length->validate(\$text), 'text is 6 characters long' );
$text = 'abcde';
ok( ! $length->try( validate => \$text ), 'text is only 5 characters long' );
is( $length->reason->type,
'data.facet.text.length',
t/data/text_facets.t view on Meta::CPAN
is( $length->reason->info,
'Text should be 6 characters long (got 5)',
'got short text error message'
);
#-----------------------------------------------------------------------
# min_length
#-----------------------------------------------------------------------
$length = FACETS->facet( 'text.min_length' => 3 );
ok( $length, 'got text.min_length facet' );
$length = FACETS->facet( text_min_length => 3 );
ok( $length, 'got text_min_length facet' );
$text = 'ab';
ok( ! $length->try( validate => \$text ), 'min length fail on 2 characters' );
is( $length->reason->info, 'Text should be at least 3 characters long (got 2)', 'min length text reason' );
$text = 'abc';
ok( $length->validate(\$text), 'min length on 3 characters' );
$text = 'abcdef';
ok( $length->validate(\$text), 'min length on 6 characters' );
#-----------------------------------------------------------------------
# max_length
#-----------------------------------------------------------------------
$length = FACETS->facet( 'text.max_length' => 3 );
ok( $length, 'got text.max_length facet' );
$length = FACETS->facet( text_max_length => { max_length => 3 } );
ok( $length, 'got text_max_length facet' );
$text = 'abcd';
ok( ! $length->try( validate => \$text ), 'max length fail on 4 characters' );
is( $length->reason->info, 'Text should be at most 3 characters long (got 4)', 'max length text reason' );
$text = 'abc';
ok( $length->validate(\$text), 'max length on 3 characters' );
$text = 'ab';
ok( $length->validate(\$text), 'max length on 2 characters' );
#-----------------------------------------------------------------------
# pattern
#-----------------------------------------------------------------------
my $pattern = FACETS->facet( 'text.pattern' => '^\w+$' );
ok( $pattern, 'got pattern facet' );
$text = 'Hello World!';
ok( ! $pattern->try( validate => \$text ), 'pattern fail on 2 words' );
is( $pattern->reason->info, 'Text does not match pattern: ^\w+$', 'pattern fail reason' );
$text = 'foo';
ok( $pattern->validate(\$text), 'pattern match on foo' );
#-----------------------------------------------------------------------
# whitespace
#-----------------------------------------------------------------------
my $fold = FACETS->facet( 'text.whitespace' => 'fold' );
ok( $fold, 'got whitespace folding facet' );
$text = "Hello\nWorld!";
ok( $fold->validate(\$text), 'called whitespace folding facet' );
is( $text, 'Hello World!', 'folded whitespace' );
my $collapse = FACETS->facet( 'text.whitespace' => 'collapse' );
ok( $collapse, 'got whitespace collapsing facet' );
$text = " \n\nHello\n\n\nBadger!\n\n\ ";
ok( $collapse->validate(\$text), 'called whitespace collapsing facet' );
is( $text, 'Hello Badger!', 'collapsed whitespace' );
__END__
#-----------------------------------------------------------------------
# any
#-----------------------------------------------------------------------
my $any = FACETS->facet( any => ['foo', 'bar'] );
ok( $any, 'got any facet' );
ok( ! $any->try( validate => 'baz' ), 'any fail on baz' );
is( $any->reason->info, 'Text does not match any of the permitted values: baz', 'any fail reason' );
ok( $any->validate('foo'), 'any match on foo' );
( run in 1.494 second using v1.01-cache-2.11-cpan-49f99fa48dc )