resolved ...
How to set the default for a non-lazy class attribute, since it
doesn't get set in a constructor?
How to avoid having these attributes show up in the object hash. This
requires messing with the inline & not-inline constructor.
Make clearer and predicate options work with class attributes.
More tests - reader, writer, predicate, clearer, coercion, lazy, etc.
use strict;
our $VERSION = '0.01';
+our $AUTHORITY = 'cpan:DROLSKY';
+
+use Moose;
+use MooseX::ClassAttribute::Meta::Method::Accessor;
+
+extends 'Moose::Meta::Attribute';
+
+sub accessor_metaclass { 'MooseX::ClassAttribute::Meta::Method::Accessor' }
+
+# This is called when an object is constructed.
+sub initialize_instance_slot
+{
+ return;
+}
+
+
+# This is the bit of magic that lets you specify the metaclass as
+# 'ClassAttribute', rather than the full name, when creating an
+# attribute.
+package Moose::Meta::Attribute::Custom::ClassAttribute;
+
+sub register_implementation { 'MooseX::ClassAttribute' }
1;
MooseX::ClassAttribute - The fantastic new MooseX::ClassAttribute!
-
=head1 SYNOPSIS
Quick summary of what the module does.
use MooseX::ClassAttribute;
- my $foo = MooseX::ClassAttribute->new;
+ my $foo = MooseX::ClassAttribute->new();
...
--- /dev/null
+package MooseX::ClassAttribute::Meta::Method::Accessor;
+
+use warnings;
+use strict;
+
+our $VERSION = '0.01';
+our $AUTHORITY = 'cpan:DROLSKY';
+
+use Moose;
+
+extends 'Moose::Meta::Method::Accessor';
+
+
+sub _inline_store {
+ my $self = shift;
+ my $instance = shift;
+ my $value = shift;
+
+ my $attr = $self->associated_attribute();
+
+ my $mi = $attr->associated_class()->get_meta_instance();
+ my $slot_name = $attr->slots();
+
+ my $package_var = sprintf q{$%s::__ClassAttribute{'%s'}}, $attr->associated_class()->name(), $slot_name;
+
+ my $code = "$package_var = $value;";
+ $code .= "Scalar::Util::weaken $package_var;"
+ if $attr->is_weak_ref();
+
+ return $code;
+}
+
+sub _inline_get {
+ my $self = shift;
+ my $instance = shift;
+
+ my $attr = $self->associated_attribute();
+
+ my $mi = $attr->associated_class()->get_meta_instance();
+ my $slot_name = $attr->slots();
+
+ return sprintf q{$%s::__ClassAttribute{'%s'}}, $attr->associated_class()->name(), $slot_name;
+}
+
+sub generate_accessor_method {
+ shift->generate_accessor_method_inline(@_);
+}
+
+sub generate_reader_method {
+ shift->generate_reader_method_inline(@_);
+}
+
+sub generate_writer_method {
+ shift->generate_writer_method_inline(@_);
+}
+
+
+1;
--- /dev/null
+use strict;
+use warnings;
+
+use lib 't/lib';
+
+use SharedTests;
+
+SharedTests::run_tests();
--- /dev/null
+use strict;
+use warnings;
+
+use lib 't/lib';
+
+use SharedTests;
+
+HasClassAttribute->meta()->make_immutable();
+
+SharedTests::run_tests();
--- /dev/null
+package SharedTests;
+
+use strict;
+use warnings;
+
+use Scalar::Util qw( isweak );
+use Test::More tests => 9;
+
+
+{
+ package HasClassAttribute;
+
+ use Moose;
+ use MooseX::ClassAttribute;
+
+ has 'ObjectCount' =>
+ ( metaclass => 'ClassAttribute',
+ is => 'rw',
+ isa => 'Int',
+ default => 0,
+ );
+
+ has 'WeakAttribute' =>
+ ( metaclass => 'ClassAttribute',
+ is => 'rw',
+ isa => 'Object',
+ weak_ref => 1,
+ );
+
+ has 'size' =>
+ ( is => 'rw',
+ isa => 'Int',
+ default => 5,
+ );
+
+ sub BUILD
+ {
+ my $class = shift;
+
+ $class->ObjectCount( $class->ObjectCount() + 1 );
+ }
+}
+
+sub run_tests
+{
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+ {
+ is( HasClassAttribute->ObjectCount(), 0,
+ 'ObjectCount() is 0' );
+
+ my $hca1 = HasClassAttribute->new();
+ is( $hca1->size(), 5,
+ 'size is 5 - object attribute works as expected' );
+ is( HasClassAttribute->ObjectCount(), 1,
+ 'ObjectCount() is 1' );
+
+ my $hca2 = HasClassAttribute->new( size => 10 );
+ is( $hca2->size(), 10,
+ 'size is 10 - object attribute can be set via constructor' );
+ is( HasClassAttribute->ObjectCount(), 2,
+ 'ObjectCount() is 2' );
+ is( $hca2->ObjectCount(), 2,
+ 'ObjectCount() is 2 - can call class attribute accessor on object' );
+ }
+
+ {
+ my $hca3 = HasClassAttribute->new( ObjectCount => 20 );
+ is( $hca3->ObjectCount(), 3,
+ 'class attributes are not affected by constructor params' );
+ is( HasClassAttribute->ObjectCount(), 3,
+ 'class attributes are not affected by constructor params' );
+ }
+
+ {
+ my $object = bless {}, 'Thing';
+
+ HasClassAttribute->WeakAttribute($object);
+
+ ok( isweak( $HasClassAttribute::__ClassAttribute{WeakAttribute} ),
+ 'weak class attributes are weak' );
+ }
+}
+
+
+1;