| MooseX-Blessed-Reconstruct documentation | Contained in the MooseX-Blessed-Reconstruct distribution. |
MooseX::Blessed::Reconstruct - A Data::Visitor for creating Moose objects from blessed placeholders
use MooseX::Blessed::Reconstruct;
my $obj = bless( {
init_arg_foo => "Blah",
arf => "yay",
}, "Foo" );
my $proper = MooseX::Blessed::Reconstruct->new->visit($obj);
# equivalent to:
my $proper = Foo->meta->new_object(%$obj);
# but recursive (and works with shared references)
The purpose of this module is to "fix up" blessed data into a real Moose object.
This is used internally by MooseX::YAML but has no implementation details having to do with YAML itself.
See Data::Visitor
Calls load_class in Class::MOP on the ref of $object.
If there's a metaclass, calls visit_object_with_meta, otherwise visit_ref
is used to walk the object brutishly.
Returns a deep clone of the input structure with all the Moose objects reconstructed "properly".
Uses the metaclass $meta to create a new instance, registers the instance
with Data::Visitor's cycle tracking, and then inflates it using
new_object in Moose::Meta::Class.
Collapses $obj into key value pairs to be used as init args to new_object in Moose::Meta::Class.
This module is maintained using Darcs. You can get the latest version from
http://nothingmuch.woobling.org/code, and use darcs send to commit
changes.
Jonathan Rockway
Yuval Kogman <nothingmuch@woobling.org>
Copyright (c) 2008 Infinity Interactive, Yuval Kogman. All rights reserved This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| MooseX-Blessed-Reconstruct documentation | Contained in the MooseX-Blessed-Reconstruct distribution. |
#!/usr/bin/perl package MooseX::Blessed::Reconstruct; use Moose; use Carp qw(croak); use Class::MOP 0.66; # well behaved load_class() use Data::Visitor 0.21; # n-arity visit use Scalar::Util qw(reftype); use namespace::clean -except => 'meta'; our $VERSION = "0.04"; extends qw(Data::Visitor); has load_classes => ( isa => "Bool", is => "rw", default => 1, ); sub visit_object { my ( $v, $obj ) = @_; my $class = ref $obj; Class::MOP::load_class($class) if $v->load_classes; my $meta = Class::MOP::get_metaclass_by_name($class); if ( ref $meta ) { return $v->visit_object_with_meta($obj, $meta); } else { return $v->visit_ref($obj); } } sub visit_object_with_meta { my ( $v, $obj, $meta ) = @_; my $instance = $meta->get_meta_instance->create_instance; $v->_register_mapping( $obj => $instance ); my $args = $v->prepare_args( $meta, $obj ); $meta->new_object( %$args, __INSTANCE__ => $instance ); return $instance; } sub prepare_args { my ( $v, $meta, $obj ) = @_; my @args; if ( reftype $obj eq 'HASH' ) { @args = %$obj; } elsif ( reftype $obj eq 'ARRAY' ) { @args = @$obj; } elsif ( reftype $obj eq 'SCALAR' ) { @args = $$obj; } else { croak "unknown ref type $obj"; } my @processed = $v->visit(@args); return $meta->name->BUILDARGS(@processed); } __PACKAGE__->meta->make_immutable; __PACKAGE__ __END__