0.02
* MooseX::Storage::Engine
- better error reporting when cycles are found
+ - class names are now stored as the full identifier
+ (<class>-<version>-<authority>) and are checked
+ when they are expanded.
+ - added docs and tests for this
0.01 Mon. April 30, 2007
This was Chris's idea originally (blame him), and
t/002_basic_w_subtypes.t
t/003_basic_w_embedded_objects.t
t/004_w_cycles.t
+t/005_w_versions_and_authority_check.t
t/010_basic_json.t
t/020_basic_yaml.t
t/100_io.t
use Moose;
use MooseX::Storage;
+ our $VERSION = '0.01';
+
with Storage('format' => 'JSON', 'io' => 'File');
has 'x' => (is => 'rw', isa => 'Int');
## object in perl data structures
# pack the class into a hash
- $p->pack(); # { __CLASS__ => 'Point', x => 10, y => 10 }
+ $p->pack(); # { __CLASS__ => 'Point-0.01', x => 10, y => 10 }
# unpack the hash into a class
- my $p2 = Point->unpack({ __CLASS__ => 'Point', x => 10, y => 10 });
+ my $p2 = Point->unpack({ __CLASS__ => 'Point-0.01', x => 10, y => 10 });
## methods to freeze/thaw into
## a specified serialization format
## (in this case JSON)
# pack the class into a JSON string
- $p->freeze(); # { "__CLASS__" : "Point", "x" : 10, "y" : 10 }
+ $p->freeze(); # { "__CLASS__" : "Point-0.01", "x" : 10, "y" : 10 }
# unpack the JSON string into a class
- my $p2 = Point->thaw('{ "__CLASS__" : "Point", "x" : 10, "y" : 10 }');
+ my $p2 = Point->thaw('{ "__CLASS__" : "Point-0.01", "x" : 10, "y" : 10 }');
## methods to load/store a class
## on the file system
use Moose;
use MooseX::Storage;
+ our $VERSION = '0.01';
+
with Storage;
has 'x' => (is => 'rw', isa => 'Int');
## object in perl data structures
# pack the class into a hash
- $p->pack(); # { __CLASS__ => 'Point', x => 10, y => 10 }
+ $p->pack(); # { __CLASS__ => 'Point-0.01', x => 10, y => 10 }
# unpack the hash into a class
- my $p2 = Point->unpack({ __CLASS__ => 'Point', x => 10, y => 10 });
+ my $p2 = Point->unpack({ __CLASS__ => 'Point-0.01', x => 10, y => 10 });
=head1 DESCRIPTION
$self->seen->{$self->object} = undef;
$self->map_attributes('collapse_attribute');
- $self->storage->{$CLASS_MARKER} = $self->object->meta->name;
+ $self->storage->{$CLASS_MARKER} = $self->object->meta->identifier;
return $self->storage;
}
my ($self, $attr, $value) = @_;
(!exists $self->seen->{$value})
|| confess "Basic Engine does not support cycles in class("
- . ($attr->associated_metaclass->name) . ").attr("
+ . ($attr->associated_class->name) . ").attr("
. ($attr->name) . ") with $value";
$self->seen->{$value} = undef;
}
my ($self, $attr, $value) = @_;
(!exists $self->seen->{$value})
|| confess "Basic Engine does not support cycles in class("
- . ($attr->associated_metaclass->name) . ").attr("
+ . ($attr->associated_class->name) . ").attr("
. ($attr->name) . ") with $value";
$self->seen->{$value} = undef;
}
my $data = shift;
(exists $data->{$CLASS_MARKER})
|| confess "Serialized item has no class marker";
- $data->{$CLASS_MARKER}->unpack($data);
+ # check the class more thoroughly here ...
+ my ($class, $version, $authority) = (split '-' => $data->{$CLASS_MARKER});
+ my $meta = eval { $class->meta };
+ confess "Class ($class) is not loaded, cannot unpack" if $@;
+ ($meta->version eq $version)
+ || confess "Class ($class) versions don't match."
+ . " got=($version) available=(" . ($meta->version || '') . ")"
+ if defined $version;
+ ($meta->authority eq $authority)
+ || confess "Class ($class) authorities don't match."
+ . " got=($authority) available=(" . ($meta->authority || '') . ")"
+ if defined $authority;
+ # all is well ...
+ $class->unpack($data);
},
collapse => sub {
my $obj = shift;
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 8;
+use Test::Exception;
+
+BEGIN {
+ use_ok('MooseX::Storage');
+}
+
+=pod
+
+This tests that the version and authority
+checks are performed upon object expansion.
+
+=cut
+
+{
+ package Bar;
+ use Moose;
+ use MooseX::Storage;
+
+ our $VERSION = '0.01';
+ our $AUTHORITY = 'cpan:JRANDOM';
+
+ with Storage;
+
+ has 'number' => (is => 'ro', isa => 'Int');
+
+ package Foo;
+ use Moose;
+ use MooseX::Storage;
+
+ our $VERSION = '0.01';
+ our $AUTHORITY = 'cpan:JRANDOM';
+
+ with Storage;
+
+ has 'bar' => (
+ is => 'ro',
+ isa => 'Bar'
+ );
+}
+
+{
+ my $foo = Foo->new(
+ bar => Bar->new(number => 1)
+ );
+ isa_ok( $foo, 'Foo' );
+
+ is_deeply(
+ $foo->pack,
+ {
+ __CLASS__ => 'Foo-0.01-cpan:JRANDOM',
+ bar => {
+ __CLASS__ => 'Bar-0.01-cpan:JRANDOM',
+ number => 1,
+ }
+ },
+ '... got the right frozen class'
+ );
+}
+
+{
+ my $foo = Foo->unpack(
+ {
+ __CLASS__ => 'Foo-0.01-cpan:JRANDOM',
+ bar => {
+ __CLASS__ => 'Bar-0.01-cpan:JRANDOM',
+ number => 1,
+ }
+ },
+ );
+ isa_ok( $foo, 'Foo' );
+ isa_ok( $foo->bar, 'Bar' );
+ is( $foo->bar->number, 1 , '... got the right number too' );
+
+}
+
+Moose::Meta::Class->create('Bar',
+ version => '0.02',
+ authority => 'cpan:JRANDOM',
+);
+
+dies_ok {
+ Foo->unpack(
+ {
+ __CLASS__ => 'Foo-0.01-cpan:JRANDOM',
+ bar => {
+ __CLASS__ => 'Bar-0.01-cpan:JRANDOM',
+ number => 1,
+ }
+ }
+ );
+} '... could not unpack, versions are different';
+
+Moose::Meta::Class->create('Bar',
+ version => '0.01',
+ authority => 'cpan:DSTATIC',
+);
+
+
+dies_ok {
+ Foo->unpack(
+ {
+ __CLASS__ => 'Foo-0.01-cpan:JRANDOM',
+ bar => {
+ __CLASS__ => 'Bar-0.01-cpan:JRANDOM',
+ number => 1,
+ }
+ }
+ );
+} '... could not unpack, authorities are different';