Handel
view release on metacpan or search on metacpan
lib/Handel/Manual/Cookbook/WritingCustomStorage.pod view on Meta::CPAN
$AUTOLOAD =~ s/^.*:://;
return unless $self->storage->has_column($AUTOLOAD);
# if we are setting, call setAttribute
if (scalar @_) {
$self->storage_result->setAttribute($AUTOLOAD, shift);
};
# return from getAttribute
$self->storage_result->getAttribute($AUTOLOAD);
};
1;
This is the easiest way to make results and the underlying storage results talk to each other. Using this
method, you can use the same result class for carts, order and cart/order items even if their fields differ.
If have a particular hatred for AUTOLOAD, you could just as well create two result classes:
Handel::Storage::XML::Cart::Result and Handel::Storage::XML::Cart::Item::Result and assign them to the
corresponding storage classes:
package Handel::Storage::XML::Cart;
use strict;
use warnings;
use base qw/Handel::Storage::XML/;
__PACKAGE__->result_class('Handel::Storage::XML::Cart::Result');
1;
package Handel::Storage::XML::Cart::Item;
use strict;
use warnings;
use base qw/Handel::Storage::XML/;
__PACKAGE__->result_class('Handel::Storage::XML::Cart::Item::Result');
1;
In each result class, you could map actual attributes to real methods instead of using autoload:
package Handel::Storage::XML::Cart::Result;
use strict
use warnings;
use base qw/Handel::Storage::Result/;
sub id {
my ($self, $value) = @_;
if ($value) {
$self->storage_result->setAttribute('id', $value);
};
return $self->storage_result->getAttribute('id');
};
=head2 Updating Results
When autoupdates are off, one has to call update manually to save the changes made to cart and item nodes.
When autoupdates are enabled, update will be called automatically on each result. To support updates we
need to create an update method on the custom result class:
sub update {
my ($self, $data) = @_;
if ($data) {
foreach my $key (keys %{$data}) {
$self->storage_result->setAttribute($key, $data->{$key});
};
};
$self->storage->save_file;
};
When update is called, the xml file is saved. If a hashref of data is supplied, it will set the appropriate
attributes and then save the changes to the xml file.
=head2 Deleting Results
Each result needs to be able to remove itself from storage. To do so, we simply need to add a delete method
to the result that removes itself and updates the file:
sub delete {
my $self = shift;
$self->storage_result->unbindNode;
$self->update;
};
=head1 USING YOUR NEW STORAGE CLASS
Now that we have a shiny new XML storage class, we need to use it. There are two ways we can go about
using our new storage class. The easiest way would be to load and configure them directly in the Cart and
Item interface classes:
package My::Cart;
use strict;
use warnings;
use base qw/Handel::Cart/;
__PACKAGE__->item_class('My::Cart::Item');
__PACKAGE__->storage_class('Handel::Storage::XML');
__PACKAGE__->storage({
add_columns => [qw/id shopper name description type/],
primary_columns => [qw/id/],
file_name => 'carts.xml',
parent_node => 'carts',
child_node => 'cart',
});
1;
While this way works, it has one problem. If you decide to change storage classes later, it may not take the
same options that this storage class does.
=head2 Create Cart and Item Storage Classes
In order to make changing storage classes less painful, it is recommended that you make subclasses of your
custom storage class to set storage options, and then use those subclasses within your Cart and Item
interface classes:
package My::Storage::Cart;
use strict;
use warnings;
( run in 0.960 second using v1.01-cache-2.11-cpan-39bf76dae61 )