Add proper thaw hooks so schema gets re-attached
Ash Berlin [Thu, 20 Dec 2007 11:02:15 +0000 (11:02 +0000)]
Changes
lib/DBIx/Class/ResultSourceHandle.pm
lib/DBIx/Class/Schema.pm
t/84serialize.t

diff --git a/Changes b/Changes
index 4c5c48e..f22d6bf 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,8 @@
 Revision history for DBIx::Class
 
+        - Added freeze, thaw and dclone methods to Schema so that thawed
+          objects will get re-attached to the schema.
+
 0.08008 2007-11-16 14:30:00
         - Fixed join merging bug (test from Zby)
         - When adding relationships, it will throw an exception if you get the
index ae11ce6..c1a5070 100644 (file)
@@ -14,6 +14,9 @@ use overload
 
 __PACKAGE__->mk_group_accessors('simple' => qw/schema source_moniker/);
 
+# Schema to use when thawing.
+our $thaw_schema;
+
 =head1 NAME
 
 DBIx::Class::ResultSourceHandle
@@ -71,20 +74,32 @@ Freezes a handle.
 
 sub STORABLE_freeze {
     my ($self, $cloning) = @_;
+
     my $to_serialize = { %$self };
+    
     delete $to_serialize->{schema};
     return (Storable::freeze($to_serialize));
 }
 
 =head2 STORABLE_thaw
 
-Thaws frozen handle.
+Thaws frozen handle. Resets the internal schema reference to the package
+variable C<$thaw_schema>. The recomened way of setting this is to use 
+C<$schema->thaw($ice)> which handles this for you.
 
 =cut
 
+
 sub STORABLE_thaw {
     my ($self, $cloning,$ice) = @_;
     %$self = %{ Storable::thaw($ice) };
+    $self->{schema} = $thaw_schema;
 }
 
+=head1 AUTHOR
+
+Ash Berlin C<< <ash@cpan.org> >>
+
+=cut
+
 1;
index b668c83..09edb9b 100644 (file)
@@ -1059,8 +1059,44 @@ L</create_ddl_dir> or L</deploy>.
 For an example of what you can do with this, see 
 L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
 
+=head2 thaw
+
+Provided as the recommened way of thawing schema objects. You can call 
+C<Storable::thaw> directly if you wish, but the thawed objects will not have a
+reference to any schema, so are rather useless
+
+=cut
+
+sub thaw {
+  my ($self, $obj) = @_;
+  local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
+  return Storable::thaw($obj);
+}
+
+=head2 freeze
+
+This doesn't actualy do anything more than call L<Storable/freeze>, it is just
+provided here for symetry.
+
 =cut
 
+sub freeze {
+  return Storable::freeze($_[1]);
+}
+
+=head2 dclone
+
+Recommeneded way of dcloning objects. This is needed to properly maintain
+references to the schema object (which itself is B<not> cloned.)
+
+=cut
+
+sub dclone {
+  my ($self, $obj) = @_;
+  local $DBIx::Class::ResultSourceHandle::thaw_schema = $self;
+  return Storable::dclone($obj);
+}
+
 1;
 
 =head1 AUTHORS
index a8cedf0..c1b67dc 100644 (file)
@@ -8,9 +8,25 @@ use Storable;
 
 my $schema = DBICTest->init_schema();
 
-plan tests => 1;
+plan tests => 6;
 
 my $artist = $schema->resultset('Artist')->find(1);
-my $copy = eval { Storable::dclone($artist) };
-is_deeply($copy, $artist, 'serialize row object works');
+
+{
+  my $copy = $schema->dclone($artist);
+  is_deeply($copy, $artist, "dclone row object works");
+  eval { $copy->discard_changes };
+  ok( !$@, "discard_changes okay" );
+  is($copy->id, $artist->id, "IDs still match ");
+}
+
+{
+  my $ice = $schema->freeze($artist);
+  my $copy = $schema->thaw($ice);
+  is_deeply($copy, $artist, 'dclone row object works');
+
+  eval { $copy->discard_changes };
+  ok( !$@, "discard_changes okay" );
+  is($copy->id, $artist->id, "IDs still okay");
+}