adding MooseX::ATtributeHelpers
[gitmo/MooseX-AttributeHelpers.git] / lib / MooseX / AttributeHelpers / Collection / Array.pm
1
2 package MooseX::AttributeHelpers::Collection::Array;
3 use Moose;
4 use Moose::Util::TypeConstraints;
5
6 our $VERSION   = '0.01';
7 our $AUTHORITY = 'cpan:STEVAN';
8
9 extends 'Moose::Meta::Attribute';
10
11 my %METHOD_CONSTRUCTORS = (
12     'push' => sub {
13         my $attr = shift;
14         return sub { 
15             my $instance = shift;
16             push @{$attr->get_value($instance)} => @_; 
17         };
18     },
19     'pop' => sub {
20         my $attr = shift;
21         return sub { pop @{$attr->get_value($_[0])} };
22     },    
23     'unshift' => sub {
24         my $attr = shift;
25         return sub { 
26             my $instance = shift;
27             unshift @{$attr->get_value($instance)} => @_; 
28         };
29     },    
30     'shift' => sub {
31         my $attr = shift;
32         return sub { shift @{$attr->get_value($_[0])} };
33     },    
34     'get' => sub {
35         my $attr = shift;
36         return sub { $attr->get_value($_[0])->[$_[1]] };
37     },    
38     'set' => sub {
39         my $attr = shift;
40         return sub { $attr->get_value($_[0])->[$_[1]] = $_[2] };
41     },    
42 );
43
44 has 'provides' => (
45     is       => 'ro',
46     isa      => subtype('HashRef' => where { 
47         (exists $METHOD_CONSTRUCTORS{$_} || return) for keys %{$_}; 1;
48     }),
49     required => 1,
50 );
51
52 has '+$!default'       => (required => 1);
53 has '+type_constraint' => (required => 1);
54
55 before '_process_options' => sub {
56     my ($self, %options) = @_;
57     
58     if (exists $options{provides}) {
59         (exists $options{isa})
60             || confess "You must define a type with the Array metaclass";  
61              
62         (find_type_constraint($options{isa})->is_subtype_of('ArrayRef'))
63             || confess "The type constraint for a Array must be a subtype of ArrayRef";
64     }
65 };
66
67 after 'install_accessors' => sub {
68     my $attr  = shift;
69     my $class = $attr->associated_class;
70     
71     foreach my $key (keys %{$attr->provides}) {
72         (exists $METHOD_CONSTRUCTORS{$key})
73             || confess "Unsupported method type ($key)";
74         $class->add_method(
75             $attr->provides->{$key}, 
76             $METHOD_CONSTRUCTORS{$key}->($attr)
77         );
78     }
79 };
80
81 no Moose;
82 no Moose::Util::TypeConstraints;
83
84 # register the alias ...
85 package Moose::Meta::Attribute::Custom::Collection;
86 sub register_implementation { 'MooseX::AttributeHelpers::Collection::Array' }
87
88
89 1;
90
91 __END__
92
93 =pod
94
95 =head1 NAME
96
97 =head1 SYNOPSIS
98
99   package Stuff;
100   use Moose;
101   
102   has 'options' => (
103       metaclass => 'Collection',
104       is        => 'ro',
105       isa       => 'ArrayRef',
106       default   => sub { [] },
107       provides  => {
108           'push' => 'add_options',
109           'pop'  => 'remove_last_option',
110       }
111   );
112
113 =head1 DESCRIPTION
114
115 =head1 METHODS
116
117 =head1 BUGS
118
119 All complex software has bugs lurking in it, and this module is no 
120 exception. If you find a bug please either email me, or add the bug
121 to cpan-RT.
122
123 =head1 AUTHOR
124
125 Stevan Little E<lt>stevan@iinteractive.comE<gt>
126
127 =head1 COPYRIGHT AND LICENSE
128
129 Copyright 2007 by Infinity Interactive, Inc.
130
131 L<http://www.iinteractive.com>
132
133 This library is free software; you can redistribute it and/or modify
134 it under the same terms as Perl itself.
135
136 =cut