CatalystX-CRUD
view release on metacpan or search on metacpan
lib/CatalystX/CRUD/Object.pm view on Meta::CPAN
package CatalystX::CRUD::Object;
use Moose;
with 'MooseX::Emulate::Class::Accessor::Fast';
with 'Catalyst::ClassData';
use base 'CatalystX::CRUD';
use Carp;
use Data::Dump qw( dump );
use MRO::Compat;
use mro 'c3';
__PACKAGE__->mk_ro_accessors(qw( delegate ));
__PACKAGE__->mk_classdata('delegate_class');
our $VERSION = '0.58';
=head1 NAME
CatalystX::CRUD::Object - an instance returned from a CatalystX::CRUD::Model
=head1 SYNOPSIS
package My::Object;
use base qw( CatalystX::CRUD::Object );
sub create { shift->delegate->save }
sub read { shift->delegate->load }
sub update { shift->delegate->save }
sub delete { shift->delegate->remove }
1;
=head1 DESCRIPTION
A CatalystX::CRUD::Model returns instances of CatalystX::CRUD::Object.
The assumption is that the Object knows how to manipulate the data it represents,
typically by holding an instance of an ORM or other data model in the
C<delegate> accessor, and calling methods on that instance.
So, for example, a CatalystX::CRUD::Object::RDBO has a Rose::DB::Object instance,
and calls its RDBO object's methods.
The idea is to provide a common CRUD API for various backend storage systems.
=head1 METHODS
The following methods are provided.
=cut
=head2 new
Generic constructor. I<args> may be a hash or hashref.
=cut
sub new {
my $class = shift;
my $arg = ref( $_[0] ) eq 'HASH' ? $_[0] : {@_};
return $class->next::method($arg);
}
=head2 delegate
The delegate() accessor is a holder for the object instance that the CXCO instance
has. A CXCO object "hasa" instance of another class in its delegate() slot. The
delegate is the thing that does the actual work; the CXCO object just provides a container
for the delegate to inhabit.
Think of delegate as a noun, not a verb, as in "The United Nations delegate often
slept here."
=head1 REQUIRED METHODS
A CXCO subclass needs to implement at least the following methods:
=over
=item create
Write a new object to store.
=item read
Load a new object from store.
=item update
Write an existing object to store.
=item delete
Remove an existing object from store.
=back
=cut
sub create { shift->throw_error("must implement create") }
sub read { shift->throw_error("must implement read") }
sub update { shift->throw_error("must implement update") }
sub delete { shift->throw_error("must implement delete") }
=head2 is_new
Return results should be boolean indicating whether the object
already exists or not. Expectation is code like:
if ($object->is_new) {
$object->create;
}
else {
$object->update;
}
=cut
sub is_new { shift->throw_error("must implement is_new") }
=head2 serialize
Stringify the object. This class overloads the string operators
to call this method.
Your delegate class should implement a serialize() method
or stringify to something useful.
=cut
sub serialize {
my $self = shift;
return "" unless defined $self->delegate;
return $self->delegate->can('serialize')
? $self->delegate->serialize
: $self->delegate . "";
}
=head2 AUTOLOAD
Some black magic hackery to make Object classes act like
they are overloaded delegate()s.
=cut
sub AUTOLOAD {
my $obj = shift;
my $obj_class = ref($obj) || $obj;
my $delegate_class = ref( $obj->delegate ) || $obj->delegate;
my $method = our $AUTOLOAD;
$method =~ s/.*://;
return if $method eq 'DESTROY';
if ( $obj->delegate->can($method) ) {
return $obj->delegate->$method(@_);
}
$obj->throw_error( "method '$method' not implemented in class "
. "'$obj_class' or '$delegate_class'" );
}
# this overrides the basic can()
( run in 0.477 second using v1.01-cache-2.11-cpan-39bf76dae61 )