X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMooseX%2FClassAttribute.pm;h=d6170f920029aada300c19de0b2f66e989ea84f5;hb=170db2d9388d36d5c035510346f8aef7808c55dd;hp=1980ce7db5eca75a04f7042026229a94a93d74f3;hpb=d48c186f81e109d93983829520df6a2e244d2cc1;p=gitmo%2FMooseX-ClassAttribute.git diff --git a/lib/MooseX/ClassAttribute.pm b/lib/MooseX/ClassAttribute.pm index 1980ce7..d6170f9 100644 --- a/lib/MooseX/ClassAttribute.pm +++ b/lib/MooseX/ClassAttribute.pm @@ -3,13 +3,14 @@ package MooseX::ClassAttribute; use strict; use warnings; -our $VERSION = '0.02'; +our $VERSION = '0.03'; our $AUTHORITY = 'cpan:DROLSKY'; our @EXPORT = 'class_has'; ## no critic ProhibitAutomaticExportation use base 'Exporter'; use B qw( svref_2object ); +use Moose::Meta::Class; use Sub::Name; @@ -17,16 +18,24 @@ sub class_has ## no critic RequireArgUnpacking { my $caller = caller(); + process_class_attribute( $caller, @_ ); + + return; +} + +sub process_class_attribute ## no critic RequireArgUnpacking +{ + my $caller = shift; + my $caller_meta = $caller->meta(); my @parents = $caller_meta->superclasses(); my $container_pkg = _make_container_class( $caller, @parents ); + my $container_meta = $container_pkg->meta(); - my $has = $container_pkg->can('has'); - $has->(@_); + $container_meta->_process_attribute(@_); - my $container_meta = $container_pkg->meta(); for my $meth ( grep { $_ ne 'instance' } $container_meta->get_method_list() ) { next if $caller_meta->has_method($meth); @@ -56,28 +65,22 @@ sub class_has ## no critic RequireArgUnpacking my @parents = map { container_class($_) || () } @_; - my $container_pkg = 'MooseX::ClassAttribute::Container::' . $caller; + push @parents, 'Moose::Object' + unless grep { $_->isa('Moose::Object') } @parents; - my $code = "package $container_pkg;\n"; - $code .= "use Moose;\n\n"; - - if (@parents) - { - $code .= "extends qw( @parents );\n"; - } - - $code .= <<'EOF'; - -my $Self; -sub instance -{ - return $Self ||= shift->new(@_); -} -EOF + my $container_pkg = 'MooseX::ClassAttribute::Container::' . $caller; + my $instance_meth = sub { + no strict 'refs'; ## no critic ProhibitNoStrict + return ${ $container_pkg . '::Self' } ||= shift->new(@_); + }; - eval $code; ## no critic ProhibitStringyEval - die $@ if $@; + my $class = + Moose::Meta::Class->create + ( $container_pkg => + superclasses => \@parents, + methods => { instance => $instance_meth }, + ); return $Name{$caller} = $container_pkg; } @@ -91,9 +94,9 @@ EOF } # This is basically copied from Moose.pm -sub unimport ## no critic RequireFinalReturn +sub unimport ## no critic RequireFinalReturn, RequireArgUnpacking { - my $caller = caller(); + my $caller = Moose::_get_caller(@_); no strict 'refs'; ## no critic ProhibitNoStrict foreach my $name (@EXPORT) @@ -168,10 +171,20 @@ the constructor will not set it. This class exports one function when you use it, C. This works exactly like Moose's C, but it declares class attributes. -Own little nit is that if you include C in your class, you +One little nit is that if you include C in your class, you won't remove the C function. To do that you must include C as well. +If you want to use this module to create class attributes in I +classes, you can call the C function like +this: + + MooseX::ClassAttribute::process_class_attribute( $package, ... ); + +The first argument is the package which will have the class attribute, +and the remaining arguments are the same as those passed to +C. + =head2 Implementation and Immutability Underneath the hood, this class creates one new class for each class