File Coverage

blib/lib/MooseX/Attribute/Dependent.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod 0 1 0.0
total 28 29 96.5


line stmt bran cond sub pod time code
1             #
2             # This file is part of MooseX-Attribute-Dependent
3             #
4             # This software is Copyright (c) 2011 by Moritz Onken.
5             #
6             # This is free software, licensed under:
7             #
8             # The (three-clause) BSD License
9             #
10             package MooseX::Attribute::Dependent;
11             {
12             $MooseX::Attribute::Dependent::VERSION = '1.1.2';
13             }
14             # ABSTRACT: Restrict attributes based on values of other attributes
15 3     3   1424061 use Moose ();
  3         8  
  3         63  
16 3     3   17 use Moose::Exporter;
  3         5  
  3         28  
17 3     3   167 use Moose::Util::MetaRole;
  3         7  
  3         66  
18 3     3   1043 use MooseX::Attribute::Dependency;
  3         11  
  3         164  
19 3     3   2674 use MooseX::Attribute::Dependent::Meta::Role::ApplicationToClass;
  3         10  
  3         120  
20 3     3   2721 use MooseX::Attribute::Dependent::Meta::Role::ApplicationToRole;
  3         10  
  3         609  
21              
22              
23             Moose::Exporter->setup_import_methods(
24             as_is => &get_dependencies,
25             class_metaroles => {
26             (Moose->VERSION >= 1.9900
27             ? (class =>
28             ['MooseX::Attribute::Dependent::Meta::Role::Class'])
29             : (constructor =>
30             ['MooseX::Attribute::Dependent::Meta::Role::Method::Constructor'])),
31             attribute => ['MooseX::Attribute::Dependent::Meta::Role::Attribute'],
32             },
33             role_metaroles => {
34             (Moose->VERSION >= 1.9900
35             ? (applied_attribute =>
36             ['MooseX::Attribute::Dependent::Meta::Role::Attribute'])
37             : ()),
38             role => ['MooseX::Attribute::Dependent::Meta::Role::Role'],
39             application_to_class => ['MooseX::Attribute::Dependent::Meta::Role::ApplicationToClass'],
40             application_to_role => ['MooseX::Attribute::Dependent::Meta::Role::ApplicationToRole'],
41            
42             },
43             );
44              
45             sub get_dependencies {
46 3     3 0 26 my $meta = Class::MOP::Class->initialize('MooseX::Attribute::Dependencies');
47 3         55 return [ map { $_->body } $meta->get_all_methods ];
  25         1343  
48             }
49              
50             1;
51              
52              
53              
54             =pod
55              
56             =head1 NAME
57              
58             MooseX::Attribute::Dependent - Restrict attributes based on values of other attributes
59              
60             =head1 VERSION
61              
62             version 1.1.2
63              
64             =head1 SYNOPSIS
65              
66             package Address;
67             use Moose;
68             use MooseX::Attribute::Dependent;
69              
70             has street => ( is => 'rw', dependency => All['city', 'zip'] );
71             has city => ( is => 'ro' );
72             has zip => ( is => 'ro', clearer => 'clear_zip' );
73              
74             no MooseX::Attribute::Dependent;
75              
76              
77             Address->new( street => '10 Downing Street' );
78             # throws error
79            
80             Address->new( street => '10 Downing Street', city => 'London' );
81             # throws error
82            
83             Address->new( street => '10 Downing Street', city => 'London', zip => 'SW1A 2AA' );
84             # succeeds
85            
86             my $address = Address->new;
87             $address->street('10 Downing Street');
88             # throws error
89            
90             $address->city('London');
91             $address->zip('SW1A 2AA');
92             $address->street('10 Downing Street');
93             # succeeds
94              
95             =head1 DESCRIPTION
96              
97             Moose type constraints restrict based on the value of the attribute.
98             Using this module, attributes can have more complex constraints, which
99             involve values of other attributes.
100             It comes with a few constraints and can easily be extended.
101              
102             =head1 AVAILABLE DEPENDENCIES
103              
104             =head2 All
105              
106             All related attributes must have a value.
107              
108             =head2 Any
109              
110             At least one related attribute must have a value.
111              
112             =head2 None
113              
114             None of the related attributes can have a value.
115              
116             =head2 NotAll
117              
118             At least one of the related attributes cannot have a value.
119              
120             =head1 CUSTOM DEPENDENCIES
121              
122             To define your own dependency, first create a class to register your
123             custom dependency. In this example, we want to restrict an attribute
124             to values smaller than serveral other attributes.
125              
126             package MyApp::Types;
127             use MooseX::Attribute::Dependency;
128             use List::MoreUtils ();
129            
130             MooseX::Attribute::Dependency::register({
131             name => 'SmallerThan',
132             message => 'The value must be smaller than %s',
133             constraint => sub {
134             my ($attr_name, $params, @related) = @_;
135             return List::MoreUtils::all { $params->{$attr_name} < $params->{$_} } @related;
136             },
137             }
138             );
139              
140             Then load C<MyApp::Types> in your class before loading C<MooseX::Attribute::Dependent>
141             and set the dependency on an attribute.
142              
143             package MyClass;
144             use Moose;
145             use MyApp::Types;
146             use MooseX::Attribute::Dependent;
147            
148              
149             has small => ( is => 'rw', dependency => SmallerThan['large'] );
150             has large => ( is => 'rw' );
151            
152             MyClass->new( small => 10, large => 1); # dies
153             MyClass->new( small => 1, large => 10); # lives
154              
155             When creating your own dependency it is important to know that there is a
156             difference in the parameters passed to the contraint function.
157             If the object is in the process of being created (e.g. C<< MyClass->new(...) >>)
158             the second parameter is a hashref and consists of the parameters passed
159             to C<new> (actually the return value of C<BUILDARGS>).
160             If the accessor of an attribute with dependency is called to set a value
161             (e.g. C<< $object->small(10) >>), the second parameter is the object itself (C<$object>).
162              
163             =head1 AUTHOR
164              
165             Moritz Onken
166              
167             =head1 COPYRIGHT AND LICENSE
168              
169             This software is Copyright (c) 2011 by Moritz Onken.
170              
171             This is free software, licensed under:
172              
173             The (three-clause) BSD License
174              
175             =cut
176              
177              
178             __END__
179