refactor code to allow for class attributes in roles
Dave Rolsky [Wed, 20 Jan 2010 22:24:18 +0000 (16:24 -0600)]
lib/MooseX/ClassAttribute.pm
lib/MooseX/ClassAttribute/Role/Meta/Class.pm
lib/MooseX/ClassAttribute/Role/Meta/Mixin/HasClassAttributes.pm
t/04-with-native-traits.t
t/05-with-attribute-helpers-backcompat.t

index 17a7d2e..9d58273 100644 (file)
@@ -21,10 +21,9 @@ sub init_meta {
         class_metaroles => {
             class => ['MooseX::ClassAttribute::Role::Meta::Class'],
         },
-
-        #        role_metaroles => {
-        #            role => ['MooseX::ClassAttribute::Role::Meta::Role'],
-        #        },
+        role_metaroles => {
+            role => ['MooseX::ClassAttribute::Role::Meta::Role'],
+        },
     );
 }
 
@@ -70,7 +69,6 @@ MooseX::ClassAttribute - Declare class attributes Moose-style
 
     My::Class->Cache()->{thing} = ...;
 
-
 =head1 DESCRIPTION
 
 This module allows you to declare class attributes in exactly the same
index e9ef9da..e51d0a6 100644 (file)
@@ -26,22 +26,25 @@ has _class_attribute_values => (
     init_arg => undef,
 );
 
-sub add_class_attribute {
+around add_class_attribute => sub {
+    my $orig = shift;
     my $self = shift;
-
-    my $attr
-        = blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
+    my $attr = (
+        blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
         ? $_[0]
-        : $self->_process_class_attribute(@_);
+        : $self->_process_class_attribute(@_)
+    );
 
-    my $name = $attr->name();
+    $self->$orig($attr);
 
-    $self->remove_class_attribute($name)
-        if $self->has_class_attribute($name);
+    return $attr;
+};
 
-    $attr->attach_to_class($self);
+sub _post_add_class_attribute {
+    my $self = shift;
+    my $attr = shift;
 
-    $self->_add_class_attribute( $name => $attr );
+    my $name = $attr->name();
 
     my $e = do {
         local $@;
@@ -53,8 +56,11 @@ sub add_class_attribute {
         $self->remove_attribute($name);
         die $e;
     }
+}
 
-    return $attr;
+sub _attach_class_attribute {
+    my ($self, $attribute) = @_;
+    $attribute->attach_to_class($self);
 }
 
 # It'd be nice if I didn't have to replicate this for class
index 82144d8..46b5a6e 100644 (file)
@@ -21,8 +21,40 @@ has _class_attribute_map => (
     init_arg => undef,
 );
 
+# deprecated
 sub get_class_attribute_map {
     return $_[0]->_class_attribute_map();
 }
 
+sub add_class_attribute {
+    my $self      = shift;
+    my $attribute = shift;
+
+    ( $attribute->isa('Class::MOP::Mixin::AttributeCore') )
+        || confess
+        "Your attribute must be an instance of Class::MOP::Mixin::AttributeCore (or a subclass)";
+
+    $self->_attach_class_attribute($attribute);
+
+    my $attr_name = $attribute->name;
+
+    $self->remove_class_attribute($attr_name)
+        if $self->has_class_attribute($attr_name);
+
+    my $order = ( scalar keys %{ $self->_attribute_map } );
+    $attribute->_set_insertion_order($order);
+
+    $self->_add_class_attribute( $attr_name => $attribute );
+
+    # This method is called to allow for installing accessors. Ideally, we'd
+    # use method overriding, but then the subclass would be responsible for
+    # making the attribute, which would end up with lots of code
+    # duplication. Even more ideally, we'd use augment/inner, but this is
+    # Class::MOP!
+    $self->_post_add_class_attribute($attribute)
+        if $self->can('_post_add_class_attribute');
+
+    return $attribute;
+}
+
 1;
index 9984e25..22abd37 100644 (file)
@@ -6,6 +6,7 @@ use Test::More;
 {
     package MyClass;
 
+    use Moose;
     use MooseX::ClassAttribute;
 
     class_has counter => (
index 9d757f6..f7bdad2 100644 (file)
@@ -12,6 +12,7 @@ BEGIN {
 {
     package MyClass;
 
+    use Moose;
     use MooseX::ClassAttribute;
     use MooseX::AttributeHelpers;