File Coverage

blib/lib/MooseX/MultiObject.pm
Criterion Covered Total %
statement 66 72 91.6
branch 5 16 31.2
condition 7 15 46.6
subroutine 17 18 94.4
pod 0 1 0.0
total 95 122 77.8


line stmt bran cond sub pod time code
1             package MooseX::MultiObject;
2             BEGIN {
3 1     1   463165 $MooseX::MultiObject::VERSION = '0.01';
4             }
5             # ABSTRACT: make a set of objects behave like a single object
6 1     1   12 use Moose ();
  1         2  
  1         24  
7 1     1   5 use Moose::Exporter;
  1         2  
  1         10  
8 1     1   718 use true;
  1         8174  
  1         9  
9 1     1   1622 use MooseX::Types::Set::Object;
  1         83673  
  1         11  
10 1     1   875 use MooseX::APIRole::Internals qw(create_role_for);
  1         2784  
  1         4  
11 1     1   160 use Moose::Util qw(does_role with_traits);
  1         2  
  1         5  
12 1     1   226 use Moose::Meta::TypeConstraint::Role;
  1         2  
  1         45  
13 1     1   363 use MooseX::MultiObject::Role;
  1         119  
  1         29  
14 1     1   458 use MooseX::MultiObject::Meta::Method::MultiDelegation;
  1         603  
  1         39  
15 1     1   5 use Set::Object qw(set);
  1         1  
  1         43  
16 1     1   4 use Carp qw(confess);
  1         1  
  1         406  
17              
18             Moose::Exporter->setup_import_methods(
19             with_meta => ['setup_multiobject'],
20             class_metaroles => { class => ['MooseX::MultiObject::Meta::Class'] },
21             );
22              
23             # eventually there will be a metaprotocol for this. for now... you
24             # will really like Set::Object, i know it.
25             sub setup_multiobject {
26 1     1 0 22797 my ($meta, %args) = @_;
27             my $attribute = $args{attribute} || {
28 1   50     12 init_arg => 'objects',
29             coerce => 1,
30             is => 'ro',
31             };
32 1   50     5 $attribute->{name} ||= 'set';
33 1   50     5 $attribute->{isa} ||= 'Set::Object';
34 1   50 0   15 $attribute->{default} ||= sub { set };
  0         0  
35 1   50     4 $attribute->{coerce} //= 1;
36 1   50     6 $attribute->{handles} ||= {};
37              
38 1 50       55 confess 'you already have a set attribute name. bailing out.'
39             if $meta->has_set_attribute_name;
40              
41 1         3 my $name = delete $attribute->{name};
42 1         8 $meta->add_attribute( $name => $attribute );
43 1         3043 $meta->set_set_attribute_name( $name ); # set is a verb and a noun!
44              
45             confess 'you must not specify both a class and a role'
46 1 0 33     5 if exists $args{class} && exists $args{role};
47              
48 1         2 my $role;
49 1 50       8 if(my $class_name = $args{class}){
    50          
50 0 0       0 my $class = blessed $class_name ? $class_name : $class_name->meta;
51 0 0       0 $role = does_role( $class, 'MooseX::APIRole::Meta' ) ?
52             $class->as_api_role : create_role_for($class);
53             }
54             elsif(my $role_name = $args{role}){
55 1 50       16 $role = blessed $role_name ? $role_name : $role_name->meta;
56 1 50       23 confess "provided role '$role' is not a Moose::Meta::Role!"
57             unless $role->isa('Moose::Meta::Role');
58              
59             }
60             else {
61 0         0 confess 'you must specify either a class or a role'; # OR DIE
62             }
63              
64 1         10 my $tc = Moose::Meta::TypeConstraint::Role->new( role => $role );
65             # $meta->set_set_type_constraint($tc);
66              
67             # add adder method -- named verbosely for maximum
68             # not-conflicting-with-stuff
69             $meta->add_method( add_managed_object => sub {
70 1     1   756 my ($self, $thing) = @_;
        1      
71 1         10 $tc->assert_valid($thing);
72 0         0 $self->$name->insert($thing);
73 0         0 return $thing;
74 1         1723 });
75              
76             # add getter
77             $meta->add_method( get_managed_objects => sub {
78 2     2   3 my ($self) = @_;
        2      
79 2         6 return $self->$name->members;
80 1         41 });
81              
82             # now invite the superdelegates
83 3         9 my @methods = grep { $_ ne 'meta' } (
84             $role->get_method_list,
85 1         32 (map { $_->name } $role->get_required_method_list),
  2         112  
86             );
87              
88 1         3 for my $method (@methods) {
89 2         64 my $metamethod = MooseX::MultiObject::Meta::Method::MultiDelegation->new(
90             name => $method,
91             package_name => $meta->name,
92             object_getter => 'get_managed_objects',
93             delegate_to => $method,
94             );
95 2         5 $meta->add_method($method => $metamethod);
96             }
97              
98 1         38 MooseX::MultiObject::Role->meta->apply($meta);
99 1         1508 $role->apply($meta);
100              
101 1         771 return $meta;
102             }
103              
104              
105              
106             =pod
107              
108             =head1 NAME
109              
110             MooseX::MultiObject - make a set of objects behave like a single object
111              
112             =head1 VERSION
113              
114             version 0.01
115              
116             =head1 SYNOPSIS
117              
118             =head1 AUTHOR
119              
120             Jonathan Rockway <jrockway@cpan.org>
121              
122             =head1 COPYRIGHT AND LICENSE
123              
124             This software is copyright (c) 2010 by Jonathan Rockway.
125              
126             This is free software; you can redistribute it and/or modify it under
127             the same terms as the Perl 5 programming language system itself.
128              
129             =cut
130              
131              
132             __END__
133