Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/monken/p5-moosex-attribute-deflator
Deflates Moose attributes to a string
https://github.com/monken/p5-moosex-attribute-deflator
Last synced: 3 months ago
JSON representation
Deflates Moose attributes to a string
- Host: GitHub
- URL: https://github.com/monken/p5-moosex-attribute-deflator
- Owner: monken
- Created: 2010-03-30T10:29:53.000Z (almost 15 years ago)
- Default Branch: master
- Last Pushed: 2016-07-05T03:06:21.000Z (over 8 years ago)
- Last Synced: 2024-06-19T15:12:58.289Z (7 months ago)
- Language: Perl
- Homepage:
- Size: 188 KB
- Stars: 3
- Watchers: 3
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.pod
- Changelog: Changes
Awesome Lists containing this project
README
package MooseX::Attribute::Deflator;
# ABSTRACT: Deflate and inflate Moose attribute values
use strict;
use warnings;
use Moose::Exporter;
use MooseX::Attribute::Deflator::Registry;
use Moose::Util qw();sub via (&) { $_[0] }
sub inline_as (&) { $_[0] }Moose::Exporter->setup_import_methods(
as_is => [ qw( deflate inflate via inline_as ) ], );my $REGISTRY = MooseX::Attribute::Deflator::Registry->new;
sub get_registry {$REGISTRY}
sub deflate {
my $types = shift;
$types = [$types] unless ( ref $types eq 'ARRAY' );
$REGISTRY->add_deflator( $_, @_ ) for (@$types);
}sub inflate {
my $types = shift;
$types = [$types] unless ( ref $types eq 'ARRAY' );
$REGISTRY->add_inflator( $_, @_ ) for (@$types);
}deflate 'Item', via {$_}, inline_as {'$value'};
inflate 'Item', via {$_}, inline_as {'$value'};Moose::Util::_create_alias( 'Attribute', 'Deflator', 1,
'MooseX::Attribute::Deflator::Meta::Role::Attribute' );1;
__END__
=head1 SYNOPSIS
package MySynopsis;
use Moose;
use DateTime;use MooseX::Attribute::Deflator;
deflate 'DateTime',
via { $_->epoch },
inline_as { '$value->epoch' }; # optional
inflate 'DateTime',
via { DateTime->from_epoch( epoch => $_ ) },
inline_as { 'DateTime->from_epoch( epoch => $value )' }; # optionalno MooseX::Attribute::Deflator;
# import default deflators and inflators for Moose types
use MooseX::Attribute::Deflator::Moose;has now => ( is => 'rw',
isa => 'DateTime',
default => sub { DateTime->now },
traits => ['Deflator'] );has hash => ( is => 'rw',
isa => 'HashRef',
default => sub { { foo => 'bar' } },
traits => ['Deflator'] );package main;
use Test::More;
my $obj = MySynopsis->new;
{
my $attr = $obj->meta->get_attribute('now');
my $deflated = $attr->deflate($obj);
like($deflated, qr/^\d+$/);my $inflated = $attr->inflate($obj, $deflated);
isa_ok($inflated, 'DateTime');
}{
my $attr = $obj->meta->get_attribute('hash');
my $deflated = $attr->deflate($obj);
is($deflated, '{"foo":"bar"}');my $inflated = $attr->inflate($obj, $deflated);
is_deeply($inflated, {foo => 'bar'})
}done_testing;
=head1 DESCRIPTION
This module consists of a a registry (L) an attribute trait L and predefined deflators and inflators
for Moose L and MooseX::Types::Strutured L.
This class is just sugar to set the inflators and deflators.You can deflate to whatever data structure you want. Loading L
will cause HashRefs and ArrayRefs to be encoded as JSON strings. However, you can simply overwrite
those deflators (and inflators) to deflate to something different like L.Unlike C, you don't need to create a deflator and inflator for every type. Instead this module
will bubble up the type hierarchy and use the first deflator or inflator it finds.This comes at a cost: B.
For extra speed, inflators and deflators can be inlined. All in/deflators that come with this
module have an inlined version as well. Whenever you implment custom type in/deflators, you
should consider writing the inlining code as well. The performance boost is immense. You
can check whether an deflator has been inlined by calling:$attr->is_deflator_inlined;
B<< Inlining works in Moose >= 1.9 only. >>
=head1 FUNCTIONS
=over 4
=item B<< deflate >>
=item B<< inflate >>
deflate 'DateTime',
via { $_->epoch },
inline_as { '$value->epoch' }; # optionalinflate 'DateTime',
via { DateTime->from_epoch( epoch => $_ ) },
inline_as { 'DateTime->from_epoch( epoch => $value )' }; # optional
Defines a deflator or inflator for a given type constraint. This can also be
a type constraint defined via L and parameterized types.The function supplied to C is called with C<$_> set to the attribute's value
and with the following arguments:=over 8
=item C<$attr>
The attribute on which this deflator/inflator has been called
=item C<$constraint>
The type constraint attached to the attribute
=item C<< $deflate/$inflate >>
A code reference to the deflate or inflate function. E.g. this is handy if you want
to call the type's parent's parent inflate or deflate method:deflate 'MySubSubType', via {
my ($attr, $constraint, $deflate) = @_;
return $deflate->($_, $constraint->parent->parent);
};=item C<$instance>
The object instance on which this deflator/inflator has been called.
=item C<@_>
Any other arguments added to L
or L.=back
For C, the parameters are handled a bit differently. The code generating subroutine
is called with the following parameters:=over 8
=item C<$constraint>
The type constraint attached to the attribute.
=item C<$attr>
The attribute on which this deflator/inflator has been called.
=item C<$registry>
my $parent = $registry->($constraint->parent);
my $code = $parent->($constraint->parent, $attr, $registry, @_);To get the code generator of a type constraint, call this function.
=back
The C function is expected to return a string. The generated code
has access to a number of variables:=over 8
=item C<$value>
Most important, the value that should be de- or inflated is stored in C<$value>.
=item C<$type_constraint>
=back
For some more advanced examples, have a look at the source of
L and L.=back
=head1 DEFLATE AN OBJECT INSTANCE
Usually, you want to deflate certain attributes of a class, but this module only
works on a per attribute basis. In order to deflate an instance with all of its
attributes, you can use the following code:sub deflate {
my $self = shift;
# you probably want to deflate only those that are required or have a value
my @attributes = grep { $_->has_value($self) || $_->is_required }
$self->meta->get_all_attributes;
# works only if all attributes have the 'Deflator' trait applied
return { map { $_->name => $_->deflate($self) } @attributes };
}If you are using L,
throw in a call to L
to make sure that you don't deflate an already deflated attribute. Instead, you can just
use L to get the deflated value.=head1 PERFORMANCE
The overhead for having custom deflators or inflators per attribute is minimal.
The file C tests three ways of deflating the value of a HashRef attribute
to a json encoded string (using L).my $obj = MyBenchmark->new( hashref => { foo => 'bar' } );
my $attr = MyBenchmark->meta->get_attribute('hashref');=over
=item deflate
$attr->deflate($obj);
Using the deflate attribute method, supplied by this module.
=item accessor
JSON::encode_json($obj->hashref);
If the attribute comes with an accessor, you can use this
method, to deflate its value. However, you need to know the
name of the accessor in order to use this method.=item get_value
JSON::encode_json($attr->get_value($obj, 'hashref'));
This solves the mentioned problem with not knowing the
accessor name.=back
The results clearly states that using the C method
adds only minimal overhead to deflating the attribute
value manually.Rate get_value deflate accessor
get_value 69832/s -- -87% -88%
deflate 543478/s 678% -- -4%
accessor 564972/s 709% 4% --