use Moose qw(confess);
use MooseX::Storage::Meta::Attribute::DoNotSerialize;
+use String::RewritePrefix ();
-our $VERSION = '0.21';
+our $VERSION = '0.26';
our $AUTHORITY = 'cpan:STEVAN';
sub import {
$pkg->meta->add_method('Storage' => __PACKAGE__->meta->find_method_by_name('_injected_storage_role_generator'));
}
+my %HORRIBLE_GC_AVOIDANCE_HACK;
+
+sub _rewrite_role_name {
+ my ($self, $base, $string) = @_;
+
+ my $role_name = scalar String::RewritePrefix->rewrite(
+ {
+ '' => "MooseX::Storage::$base\::",
+ '=' => '',
+ },
+ $string,
+ );
+}
+
+sub _expand_role {
+ my ($self, $base, $value) = @_;
+
+ return unless defined $value;
+
+ if (ref $value) {
+ confess "too many args in arrayref role declaration" if @$value > 2;
+ my ($class, $param) = @$value;
+
+ $class = $self->_rewrite_role_name($base => $class);
+ Class::MOP::load_class($class);
+
+ my $role = $class->meta->generate_role(parameters => $param);
+
+ $HORRIBLE_GC_AVOIDANCE_HACK{ $role->name } = $role;
+ return $role->name;
+ } else {
+ my $class = $self->_rewrite_role_name($base, $value);
+ Class::MOP::load_class($class);
+
+ my $role = $class;
+
+ if ($class->meta->isa(
+ 'MooseX::Role::Parameterized::Meta::Role::Parameterizable'
+ )) {
+ $role = $class->meta->generate_role(parameters => undef);
+ $HORRIBLE_GC_AVOIDANCE_HACK{ $role->name } = $role;
+ return $role->name;
+ }
+
+ return $class;
+ }
+}
+
sub _injected_storage_role_generator {
my %params = @_;
- if (exists $params{'base'}) {
- $params{'base'} = ('Base::' . $params{'base'});
- }
- else {
- $params{'base'} = 'Basic';
- }
+ $params{base} = '=MooseX::Storage::Basic' unless defined $params{base};
- my @roles = (
- ('MooseX::Storage::' . $params{'base'}),
- );
+ my @roles = __PACKAGE__->_expand_role(Base => $params{base});
# NOTE:
# you don't have to have a format
# role, this just means you dont
# get anything other than pack/unpack
- push @roles => 'MooseX::Storage::Format::' . $params{'format'}
- if exists $params{'format'};
+ push @roles, __PACKAGE__->_expand_role(Format => $params{format});
# NOTE:
# many IO roles don't make sense unless
# you have also have a format role chosen
# too, the exception being StorableFile
- if (exists $params{'io'}) {
- # NOTE:
- # we dont need this code anymore, cause
- # the role composition will catch it for
- # us. This allows the StorableFile to work
- #(exists $params{'format'})
- # || confess "You must specify a format role in order to use an IO role";
- push @roles => 'MooseX::Storage::IO::' . $params{'io'};
- }
+ #
+ # NOTE:
+ # we dont need this code anymore, cause
+ # the role composition will catch it for
+ # us. This allows the StorableFile to work
+ #(exists $params{'format'})
+ # || confess "You must specify a format role in order to use an IO role";
+ push @roles, __PACKAGE__->_expand_role(IO => $params{io});
# Note:
# These traits alter the behaviour of the engine, the user can
# specify these per role-usage
for my $trait ( @{ $params{'traits'} ||= [] } ) {
- push @roles, 'MooseX::Storage::Traits::'.$trait;
- }
-
- for my $role ( @roles ) {
- Class::MOP::load_class($role) or die "Could not load role ($role)";
+ push @roles, __PACKAGE__->_expand_role(Traits => $trait);
}
return @roles;
is by no means the only way. You can still compose your roles by
hand if you like.
+By default, options are assumed to be short forms. For example, this:
+
+ Storage(format => 'JSON');
+
+...will result in looking for MooseX::Storage::Format::JSON. To use a role
+that is not under the default namespace prefix, start with an equal sign:
+
+ Storage(format => '=My::Private::JSONFormat');
+
+To use a parameterized role (for which, see L<MooseX::Role::Parameterized>) you
+can pass an arrayref of the role name (in short or long form, as above) and its
+parameters:
+
+ Storage(format => [ JSONpm => { json_opts => { pretty => 1 } } ]);
+
=back
=head1 METHODS