DBIx-SQLEngine

 view release on metacpan or  search on metacpan

SQLEngine/Record/Hooks.pm  view on Meta::CPAN

=head1 NAME

DBIx::SQLEngine::Record::Hooks - Flexible Pre/Post Hooks

=head1 SYNOPSIS

B<Setup:> Several ways to create a class.

  my $sqldb = DBIx::SQLEngine->new( ... );

  $class_name = $sqldb->record_class( $table_name, undef, 'Hooks' );
  
  $sqldb->record_class( $table_name, 'My::Record', 'Hooks' );
  
  package My::Record;
  use DBIx::SQLEngine::Record::Class '-isasubclass', 'Hooks';  
  My::Record->table( $sqldb->table($table_name) );

B<Hooks:> Register subs for callbacks.

  DBIx::SQLEngine::Record::Hooks->install_hooks( 
    post_new    => sub { warn "Record $_[0] created" },
    post_fetch  => sub { warn "Record $_[0] loaded" },
    post_insert => sub { warn "Record $_[0] inserted" },
    post_update => sub { warn "Record $_[0] updated" },
    post_delete => sub { warn "Record $_[0] deleted" },
  );
  
  $class_name->install_hooks( %hook_subs );

  $record->install_hooks( %hook_subs );

B<Basics:> Layered over superclass.

  # Calls post_fetch hooks on record
  $record = $class_name->fetch_record( $primary_key );

  # Calls post_fetch hooks on each record
  @records = $class_name->fetch_select(%clauses)->records;
  
  # Calls post_new hooks on empty record
  $record = $class_name->new_with_values(somefield => 'My Value');

  # Calls ok_insert, pre_insert, and post_insert hooks
  $record->insert_record();
  
  # Calls ok_update, pre_update, and post_update hooks
  $record->update_record();
  
  # Calls ok_delete, pre_delete, and post_delete hooks
  $record->delete_record();


=head1 DESCRIPTION

This package provides a callback layer for DBIx::SQLEngine::Record objects.

Don't use this module directly; instead, pass its name as a trait when you create a new record class. This package provides a multiply-composable collection of functionality for Record classes. It is combined with the base class and other traits by D...

=cut

########################################################################

package DBIx::SQLEngine::Record::Hooks;

use strict;
use Carp;

########################################################################

########################################################################

=head1 HOOKS INTERFACE

Many of the methods below are labeled "Inheritable Hook." These methods allow you to register callbacks which are then invoked at specific points in each record's lifecycle. You can add these callbacks to all record classes, to a particular class, or...

These hooks act like the triggers supported by some databases; you can ensure that every time a record is updated in a specific table, certain other actions occur automatically.

To register a callback, call the install_hooks method, and pass it pairs of a hook method name, and a subroutine reference, as follows: I<callee>->install_hooks( I<methodname> => I<coderef>, ... ).

=over 4

=item install_hooks()

  $classname->install_hooks( $hook_name => \&my_sub, ... )
  $record->install_hooks( $hook_name => \&my_sub, ... )

Registers one or more callbacks. Accepts pairs of a hook method name, and a subroutine reference. 

For more about the implementation of the Hook mechanism, see L<Class::MakeMethods::Composite::Inheritable>.

=back

B<Examples:>

Here are a few examples to show the possibilities this provides you with:

=over 4

=item *

To have each record write to a log when it's loaded from the database:

  sub log_fetch { my $record = shift; warn "Loaded record $record->{id}" } );
  MyClass->install_hooks( post_fetch => \&log_fetch );

=item *

To make a class "read-only" by preventing all inserts, updates, and deletes:

  my $refusal = sub { return 0 };
  MyClass->install_hooks( 
    ok_insert => $refusal, 
    ok_update => $refusal, 
    ok_delete => $refusal, 
  );

=item *

To have a particular record automatically save any changes you've made to it when it goes out of scope:

  my $record = MyClass->fetch_one( ... );
  $record->install_hooks( pre_destroy => sub { (shift)->save_record } );

=back

=cut

sub install_hooks {
  my $callee = shift;
  while ( my( $method_name, $code_ref ) = splice( @_, 0, 2 ) ) {
    $callee->$method_name( 
      Class::MakeMethods::Composite::Inheritable->Hook( $code_ref )
    );
  }
}

########################################################################

########################################################################

=head1 SIMPLE RECORD INTERFACE

=head2 Constructor

You may create your own records for new instances, or fetch records from the database as described in L</"FETCHING DATA (SQL DQL)">

=over 4



( run in 3.122 seconds using v1.01-cache-2.11-cpan-364913b4093 )