NAME
    Tie::Assert - Enforces restrictions on variables' contents

VERSION
    This document refers to version 0.12 of Tie::Assert, released October
    13th 2004.

SYNOPSIS
      # Tie a few scalars...
      my $dna;
      tie ($dna, 'Tie::Assert::Scalar',
        sequenceCheck => Tie::Assert::CheckFactory->regex(qr/^[gatc]*$/i),
      );
      $dna = 'gattaca'; # Fine, it matches the regex.
      $dna = 'wibble';  # Doesn't match regex, will cause an error.

      my $percentage_score;
      tie ($percentage_score, 'Tie::Assert::Scalar',
        rangeCheck => Tie::Assert::CheckFactory->range(0 => 100),
      );
      $percentage_score = 23;  # Fine, well within the range provided.
      $percentage_score = 201; # An invalid percentage score, more errors.

      my $positive_integer;
      tie ($positive_integer, 'Tie::Assert::Scalar',
        positiveCheck => Tie::Assert::CheckFactory->min(0),
        integerCheck  => Tie::Assert::CheckFactory->integer_ok(),
      );
      $positive_number = 23;   # A valid positive number
      $positive_number = -1;   # Invalid, another error.

DESCRIPTION
    Tie::Assert is designed to fill the niche when Perl developers need to
    guarantee that a variable obeys certain rules at all times, times when
    users of others languages would rely on assert() and type-checking.

    This module is intended to be as flexible as possible, allowing the
    developer to use it to do things as basic as ensuring a variable is
    numeric and dying with an error message if not, up to ensuring a string
    contains a valid and existing account number, and mailing a support
    account if it's ever invalid.

    Flexibility is the primary goal here, this module's useful for working
    out where a program's setting it's variables to invalid values, to
    providing a certain added level of security by ensuring variables cannot
    be changed to out-of-range values.

    Anywhere a value has to remain within a particular range this module
    could potentially be useful.

BASIC USAGE
    To use Tie::Assert in it's most common way you create a series of checks
    with the methods of Tie::Assert::CheckFactory, and tie them do a
    variable via the Tie::Assert::* family of modules.

    For example, suppose we're going to ensure a variable is a positive
    number, we can start by using the is_number() and min() functions of
    CheckFactory to produce the following two checks:

      my $number_check   = Tie::Assert::CheckFactory->is_number();
      my $positive_check = Tie::Assert::CheckFactory->min(0);

    Now we can create our variable and tie it to these two checks, giving
    them meaningful names in the control hash for tie(). The variable's a
    scalar so we'll be using Tie::Assert::Scalar as the checker.

      my $positive_number;
  
      # We're tying $positive_number to a 'Tie::Assert::Scalar' checker..
      tie ($positive_number, 'Tie::Assert::Scalar',
        # .. call the number check is_number, this'll be displayed in
        #  the error if an assignment tries to set it to something
        #  not a number..
        is_number   => $number_check,
        # .. similarly call the positive number check is_positive.
        is_positive => $positive_number,
      );

    That's all there is to it. Now if we try and assign a value to the
    $positive_number variable which isn't a positive number it'll draw our
    attention to the problem by quitting the program with a nice meaningful
    error message.

ADVANCED TOPICS
  Obtaining the tied object
    When Perl ties a variable it creates an object which methods are called
    on behind the scenes, it's this object that other methods can be called
    upon to change the way the Tie::Assert class affects it.

    There's a keyword named tied() which returns the object behind a given
    tied variable, so we can obtain the object behind $positive_number by:

      my $positive_number_object = tied($positive_number);

    If we want we can skip storing the tied object in a variable itself and
    simply call methods directly on it, it's this format that'll be used
    below.

  Adding and removing checks on the fly
    Sometimes it's convenient to be able to change the checks on a variable
    at run time, and here's where you want to be able to add and remove
    checks from the variable yourself rather than just relying on those
    configured by the tie().

    To add a check call add_check() on the tied object, providing it with a
    check name and check as you did in the constructor.

      tied($variable)->add_check(
        oneToTen => Tie::Assert::CheckFactory->range(1=>10),
      );

    If there was already a check assigned to the variable with the given
    name then it will be replaced by the new one.

    To remove a check call remove_check() providing it with the check name
    only.

      tied($variable)->remove_check('oneToTen');

    A final removal method remove_all_checks() will destroy all of the
    checks on a given variable.

      tied($variable)->remove_all_checks();

  Obtaining information on the current checks
    There's a couple of methods to query the filters assigned to a given
    variable, the first is a simple count of the number of filters currently
    attached to a variable:

      print "Currently  ",tied($variable)->count_filters," filters\n";

    A complete list of filters can be obtained by calling the filter_names()
    method:

      for my $filter_name (tied($variable)->filter_names) {
        print "Got filter $filter_name\n";
      }
  
  Changing the error handler
    Often the developer doesn't want the entire program to die when it's
    given an invalid value, they simply want it to log it, or even just
    ignore the assignment. The Tie::Assert system handles this through the
    set_error_handler() method that all tie'able classes in the system
    support, to use it simply call set_error_handler() on the tied object
    (See 'Obtaining the tied object' above) and pass it either a code
    fragment, or a code reference to a function to handle the error. Either
    way the function you provide should accept one parameter, the name of
    the check.

    So, if we had had a logging object with a log() method we may set the
    error handler by calling:

      tied($variable)->set_error_handler(
        sub {$logger->log("Assert error, '".shift()."' check failed");
      );

    If we had a method to do the logging it's even easier.

      tied($variable)->set_error_handler( \&log_assert_error );
  
      ...
  
      sub log_assert_error {
        my ($check_name) = @_;
        $logger->log("Assert error, '".$check_name."' check failed");`
      }

  Providing your own custom checks
    The CheckFactory provides functionality sufficient to cover the most
    common uses, but sometimes there's need to be able to add your own
    custom checks.

    The secret here is that the CheckFactory itself simply returns a closure
    which takes the value as it's sole parameter and returns a boolean
    indicating whether it's allowed the value or not. To create your own
    check it's just a case of providing your own closure or function pointer
    with the same 'true for accept, false for error' behavior.

    So, if I wanted to add a filter based on only allowing odd numbers..

      tied($variable)->add_check(isOdd, sub { $_[0] % 2 });

  Enabling and disabling the entire Test::Assert system
    Sometimes in development there's a need to have stringent checking, but
    when it hits live the error handler slows the process down too much.

    The ideal solution to this is to replace the error handler with a
    lighter version, thus keeping Tie::Assert's checks in the most vital
    environment, but for times when this is not required it's possible to
    disable the entire Tie::Assert framework with one single call.

      Tie::Assert->disable;

    ... will turn off all assertions, allowing any values to be stored
    again, and ...

      Tie::Assert->enable;

    ... will again enable the assertions, with none of the configuration of
    them lost during their disabled time.

    Note that the global enabling and disabling of the Assert system will
    not change the filters reported as being attached to a variable, they're
    still attached there even when they're not active.

NOTE
    This module is ALPHA code, it's seemed stable in a number of projects
    but the interface is liable to change before the final release.

    Developments expected in future versions include:

    Adding Tie::Assert::Array
        This should allow the use of assertions on both the index and value
        of an array.

    Adding Tie::Assert::Hash
        This should allow the use of assertions on both the key and the
        value of a hash.

    Boolean Checks
        Composite methods allowing you to combine multiple checks with AND
        or OR logic, or reverse the result of a single test with a NOT.

    PresentIn Checks
        Basically an enumeration, restricts the value to those provided.

    Length Checks
        Restrictions based on the length of a string.

    More comprehensive error messages
        The error handlers should also receive the value which caused the
        error, and the original value.

    Hopefully a version with all of these changes should be released within
    a week or so.

BUGS
    No known bugs at present.

SEE ALSO
    Tie::Aspect::CheckFactory, Tie::Aspect::Scalar

AUTHOR
    Paul Golds (Paul.Golds@GMail.com)

COPYRIGHT
    Copyright (c) 2004, Paul Golds. All Rights Reserved. This module is free
    software. It may be used, redistributed, and/or modified under the same
    terms as Perl itself.

