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