Brick - Complex business rule data validation
use Brick;
my $brick = Brick->new( {
external_packages => [ qw(Foo::Validator Bar::Validator) ]
} );
my $profile = Brick::Profile->new( $brick,
[ required => sub { .... } => $hash ],
[ optional => optional_fields => $hash ],
[ inside => in_number => $hash ],
[ outside => ex_number => $hash ],
);
my %input_from_app = (
name => 'Joe Snuffy',
...
);
my $results = $brick->apply( $profile, \%%input_from_app );
Create a new Brick. Currently this doesn't do anything other than
give you an object so you can call methods.
Future ideas? Maybe store several buckets or profiles?
Set the error message from the last things that happened.
Get the error message from the last things that happened.
This method creates a Brick::Bucket instance (or an instance in
the package returned by $brick-bucket_class> ) based on the profile
and returns the bucket instance. Along the way it affects the args
hashref in each profile element to add the element name as the key
profile_name and the actual coderef (not just the method name) as
the key code. The closure generators are allowed to use those keys.
For instance, __make_constraint, which is usually the top level
closure, uses it to name the closure in the bucket.
If the profile doesn't pass lint test, this method croaks. You
might want to safeguard that by calling lint first.
my $bucket = do {
if( my( $lint ) = $brick->lint( $profile ) )
{
$brick->create_bucket( $profile );
}
else
{
Data::Dumper->Dump( [ $lint ], [qw(lint)] );
undef;
}
};
From the profile it extracts the method name to create the closure for it based on its arguments. If the method item is already a code reference it uses it add is, but still adds it to the bucket. This could be handy for using closures from other classes, but I haven't investigated the consequences of that.
In scalar context this returns a new bucket instance. If the profile might be bad, use an eval to catch the croak:
my $bucket = eval{ $brick->create_bucket( \@profile ) };
In list context, it returns the $bucket instance and an anonymous array
reference with the stringified closures (which are also the keys in the
bucket). The elements in the anonymous array correspond to the elements in
the profile. This is handy in explain which needs to find the bucket
entries for each profile elements. You probably won't need the second
argument most of the time.
my( $bucket, $refs ) = eval { $brick->create_bucket( \@profile ) };
Initialize the instance, or return it to a pristine state. Normally
you don't have to do this because new does it for you, but if you
subclass this you might want to override it.
Load external validator packages into the bucket. Each of these packages
should export the functions they want to make available. add_validator_package
requires each package and calls its import routine.
Based on the current instance, create another one just like it but not
connected to it (in effect forking the instance). After the clone
you can change new instance without affecting the old one. This is
handy in explain, for instance, where I want a deep copy for a
moment. At least I think I want a deep copy.
That's the idea. Right now this just returns the same instance. When not using a copy breaks, I'll fix that.
Turn the profile into a textual description without applying it to any data. This does not add the profile to instance and it does not add the constraints to the bucket.
If everything goes right, this returns a single string that represents the profile.
If the profile does not pass the lint test, this returns undef or the
empty list.
If you want to do something with a datastructure, you probably want to write a different method very similar to this instead of trying to parse the output.
Future notes: maybe this is just really a dispatcher to things that do it in different ways (text output, hash output).
The namespace that apply uses for its result object. By default
this is Brick::Result. If you don't like that, override this in a
subclass. Things that need to work with the result class name, such as
a factory method, will use the return value of this method.
The namespace for the profile object. By default this is
Brick::Profile. If you don't like that, override this in a
subclass. Things that need to work with the result class name, such as
a factory method, will use the return value of this method.
TBA
the Brick::Tutorial manpage, the Brick::UserGuide manpage
This source is part of a SourceForge project which always has the latest sources in SVN, as well as all of the previous releases.
svn co https://brian-d-foy.svn.sourceforge.net/svnroot/brian-d-foy brian-d-foy
If, for some reason, I disappear from the world, one of the other members of the project can shepherd this module appropriately.
brian d foy, <bdfoy@cpan.org>
Copyright (c) 2007, brian d foy, All Rights Reserved.
You may redistribute this under the same terms as Perl itself.