Alzabo

 view release on metacpan or  search on metacpan

lib/Alzabo/ChangeTracker.pm  view on Meta::CPAN

package Alzabo::ChangeTracker;

use strict;

use vars qw( $VERSION $STACK @CHANGES );

$VERSION = 2.0;

use Params::Validate qw( :all );
Params::Validate::validation_options( on_fail => sub { Alzabo::Exception::Params->throw( error => join '', @_ ) } );

1;

sub new
{
    my $proto = shift;
    my $class = ref $proto || $proto;

    ++$STACK;

    my $self = $STACK;
    bless \$self, $class;
}

sub add
{
    my $self = shift;

    validate_pos( @_, { type => CODEREF } );

    push @CHANGES, shift;
}

sub backout
{
    my $self = shift;

    $_->() foreach @CHANGES;

    @CHANGES = ();
}

sub DESTROY
{
    --$STACK;

    @CHANGES = () unless $STACK;
}

__END__

=head1 NAME

Alzabo::ChangeTracker - Saves a set of changes as callbacks that can be backed out if needed

=head1 SYNOPSIS

  use Alzabo::ChangeTracker;

  my $x = 0;
  my $y = 1;
  sub foo
  {
     my $tracker = Alzabo::ChangeTracker->new;
     $tracker->add( sub { $x = 0; } );

     $x = 1;

     bar();

     eval { something; };

     $tracker->backout if $@;
  }

  sub bar
  {
     my $tracker = Alzabo::ChangeTracker->new;
     $tracker->add( sub { $y = 1; } );

     $y = 2;
  }


=head1 DESCRIPTION

The trick ...

We only want to have one object of this type at any one time.  In



( run in 0.627 second using v1.01-cache-2.11-cpan-39bf76dae61 )