Some more documentation updates.
[gitmo/MooseX-AttributeHelpers.git] / lib / MooseX / AttributeHelpers / Composite / Trait.pm
1 package MooseX::AttributeHelpers::Composite::Trait;
2 use Moose::Role;
3 use MooseX::AttributeHelpers::MethodProvider;
4 use MooseX::AttributeHelpers::Meta::Method::Provided;
5
6 has provides => (
7     is      => 'ro',
8     isa     => 'HashRef',
9     default => sub { {} },
10 );
11
12 after install_accessors => sub {
13     my $attr  = shift;
14     my $class = $attr->associated_class;
15
16     my $provides = $attr->provides;
17
18     foreach my $method_provider (keys %$provides) {
19         my $typename = get_provider_type($method_provider);
20         confess "Attribute must be of type $typename to use $method_provider"
21             unless ($attr->has_type_constraint
22                     && $attr->type_constraint->is_a_type_of($typename));
23     
24         my $spec = $provides->{$method_provider};
25         my $factories = get_provider_methods($method_provider, $spec);
26
27         foreach my $method_name (keys %$factories) {
28             confess "$method_name already exists in class " . $class->name
29                 if $class->has_method($method_name);
30
31             my $method = MooseX::AttributeHelpers::Meta::Method::Provided->wrap(
32                 $factories->{$method_name}->(
33                     $attr, 
34                     $attr->get_read_method_ref, 
35                     $attr->get_write_method_ref
36                 ),
37             );
38             $attr->associate_method($method);
39             $class->add_method($method_name => $method)
40         }
41     }
42 };
43
44 1;
45
46 __END__
47
48 =pod
49
50 =head1 NAME
51
52 MooseX::AttributeHelpers::Composite:Trait
53
54 =head1 SYNOPSIS
55
56     package Foo;
57     use Moose;
58     use MooseX::AttributeHelpers;
59     
60     has foo => (
61         #metaclass => 'Composite',
62         traits    => ['MooseX::AttributeHelpers::Composite::Trait'],
63         is        => 'ro',
64         isa       => 'Int',
65         default   => 0,
66         provides  => {
67             Counter => {
68                 inc   => 'inc_foo',
69                 reset => 'reset_foo',
70             },
71             Number => {
72                 mul   => 'mul_foo',
73             },
74             # My::Method::Provider => {
75             #     some_method => 'foo_method',
76             #},
77         },
78     );
79     
80     package main;
81     
82     my $foo = Foo->new;
83     $foo->inc_foo;
84     $foo->mul_foo(3);
85     print $foo->foo . "\n";
86     # 3
87
88 =head1 DESCRIPTION
89
90 This is an expansion on the basic L<MooseX::AttributeHelpers> idea, allowing you
91 to compose the methods provided by the various
92 L<MethodProviders|MooseX::AttributeHelpers::MethodProvider> without naming
93 conflicts.  In addition, this module provides a way to get these helper
94 methods without being locked into a particular
95 L<metaclass|MooseX::AttributeHelpers::Composite>, as it is simply a role with
96 a provides attribute and a method modifier.  It cannot, however, be used with
97 old-style AttributeHelpers - the 'provides' name will conflict.
98
99 =head1 ATTRIBUTES
100
101 =over 4
102
103 =item provides
104
105 The map that tells Composite which methods from which providers you would like
106 installed under which names.  It follows the format 
107
108     ProviderName => {
109         provided_method => desired_method_name,
110         ...
111     },
112     AnotherProvider => {
113         ...
114     },
115     ...
116
117 =back
118
119 =head1 BUGS
120
121 All complex software has bugs lurking in it, and this module is no
122 exception. If you find a bug please either email me, or add the bug
123 to cpan-RT.
124
125 =head1 AUTHOR
126
127 Paul Driver E<lt>frodwith@cpan.orgE<gt>
128
129 =cut