Skip to content

Instantly share code, notes, and snippets.

@jjn1056
Created September 9, 2019 13:55
Show Gist options
  • Save jjn1056/487833280fa6b8cb45ca17bc7b351705 to your computer and use it in GitHub Desktop.
Save jjn1056/487833280fa6b8cb45ca17bc7b351705 to your computer and use it in GitHub Desktop.
use Test::Most;
use Devel::Dwarn;
{
package Valiant::Scalar;
use Moo::Role;
our $rules_initialized = 0;
our @rules =();
sub rules {
my $class = shift;
$class = ref($class) if ref($class);
no strict 'refs';
unless( ${"${class}::rules_initialized"} ) {
my $sub; $sub = sub {
my $parent = shift;
my @parent_rules = $parent->rules if $parent->can('rules');
return unless @parent_rules;
push @{"${class}::rules"}, @parent_rules;
$sub->($_) for @{"${parent}::ISA"};
};
$sub->($_) for (@{"${class}::ISA"});
${"${class}::rules_initialized"} = 1;
}
@{"${class}::rules"} = @_ if @_;
return @{"${class}::rules"};
}
sub add_rule {
my ($class, $rule) = @_;
$class->rules($class->rules, $rule);
return $class;
}
package Valiant::Scalar::Silly;
use Moo::Role;
with 'Valiant::Scalar';
has silly => (is=>'ro', required=>0, default=>'silly');
Valiant::Scalar::Silly->add_rule({
silly => sub {
my ($self, $value) = @_;
return "Too silly" unless $self->silly ne 'silly';
},
});
package Valiant::Scalar::String;
use Moo;
with 'Valiant::Scalar', 'Valiant::Scalar::Silly';
has min => (is=>'ro', required=>0, default=>0);
has max => (is=>'ro', required=>0, default=>1);
Valiant::Scalar::String->add_rule({
min => sub {
my ($self, $value) = @_;
return "Too short, needs to be at least ${\$self->min} characters" unless length($value) >= $self->min;
},
});
Valiant::Scalar::String->add_rule({
max => sub {
my ($meta_self, $self, $value) = @_;
return "Too long, needs to be no more than ${\$self->max} characters" unless length($value) <= $self->max;
},
});
package Valiant::Scalar::Password;
use Moo;
extends 'Valiant::Scalar::String';
has 'min_numbers' => (is=>'ro', required=>1, default=>1);
has 'min_uppercase' => (is=>'ro', required=>1, default=>1);
Valiant::Scalar::Password->add_rule({
at_least_one_number => sub {
my ($meta_self, $self, $value) = @_;
return "Must have at least ${\$self->min_numbers} number" unless $value=~/\d{${\$self->min_numbers},}/;
},
});
Valiant::Scalar::Password->add_rule({
at_least_one_uppercase => sub {
my ($meta_self, $self, $value) = @_;
return "Must have at least ${\$self->min_uppercase} uppercase letter" unless $value=~/[A-Z]{${\$self->min_uppercase},}/;
},
});
}
ok my $string_v = Valiant::Scalar::String->new(min=>2, max=>12);
Dwarn $string_v;
Dwarn [$string_v->rules];
ok my $pass_v = Valiant::Scalar::Password->new(min=>2, max=>12);
Dwarn $pass_v;
Dwarn [$pass_v->rules];
Dwarn $string_v;
Dwarn [$string_v->rules];
done_testing;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment