File Coverage

blib/lib/Fey/ORM/Policy.pm
Criterion Covered Total %
statement 24 24 100.0
branch n/a
condition 2 3 66.6
subroutine 12 12 100.0
pod 7 7 100.0
total 45 46 97.8


line stmt bran cond sub pod time code
1             package Fey::ORM::Policy;
2              
3 1     1   4601003 use strict;
  1         2  
  1         26  
4 1     1   4 use warnings;
  1         2  
  1         39  
5              
6             our $VERSION = '0.47';
7              
8 1     1   390 use Fey::Object::Policy;
  1         4  
  1         63  
9              
10             {
11             my @subs;
12              
13             BEGIN {
14 1     1   67 @subs = qw(
15             Policy
16             transform_all
17             matching
18             inflate
19             deflate
20             has_one_namer
21             has_many_namer
22             );
23             }
24              
25 1         20 use Sub::Exporter -setup => {
26             exports => \@subs,
27             groups => { default => \@subs },
28 1     1   11 };
  1         3  
29             }
30              
31             ## no critic (Subroutines::ProhibitSubroutinePrototypes)
32              
33             # I could use MooseX::ClassAttribute and add a class attribute to the
34             # calling class, but really, that class doesn't need to use Moose,
35             # since it's just a name we can use to find the associated policy
36             # object.
37             {
38             my %Policies;
39              
40             sub Policy {
41 8     8 1 31 my $caller = shift;
42              
43 8   66     179 return $Policies{$caller} ||= Fey::Object::Policy->new();
44             }
45             }
46              
47             sub transform_all {
48 1     1 1 4 my $class = caller();
49              
50 1         9 $class->Policy()->add_transform( {@_} );
51             }
52              
53             sub matching (&) {
54 1     1 1 22 return ( matching => $_[0] );
55             }
56              
57             sub inflate (&) {
58 1     1 1 6 return ( inflate => $_[0] );
59             }
60              
61             sub deflate (&) {
62 1     1 1 5 return ( deflate => $_[0] );
63             }
64              
65             sub has_one_namer (&) {
66 1     1 1 3 my $class = caller();
67              
68 1         4 $class->Policy()->set_has_one_namer( $_[0] );
69             }
70              
71             sub has_many_namer (&) {
72 1     1 1 2 my $class = caller();
73              
74 1         3 $class->Policy()->set_has_many_namer( $_[0] );
75             }
76              
77             1;
78              
79             # ABSTRACT: Declarative policies for Fey::ORM using classes
80              
81             __END__
82              
83             =pod
84              
85             =head1 NAME
86              
87             Fey::ORM::Policy - Declarative policies for Fey::ORM using classes
88              
89             =head1 VERSION
90              
91             version 0.47
92              
93             =head1 SYNOPSIS
94              
95             package MyApp::Policy;
96              
97             use strict;
98             use warnings;
99              
100             use Fey::ORM::Policy;
101             use Lingua::EN::Inflect qw( PL_N );
102              
103             transform_all
104             matching { $_[0]->type() eq 'date' }
105              
106             => inflate { return unless defined $_[1];
107             return DateTime::Format::Pg->parse_date( $_[1] ) }
108              
109             => deflate { defined $_[1] && ref $_[1]
110             ? DateTime::Format::Pg->format_date( $_[1] )
111             : $_[1] };
112              
113             transform_all
114             matching { $_[0]->name() eq 'email_address' }
115              
116             => inflate { return unless defined $_[1];
117             return Email::Address->parse( $_[1] ) }
118              
119             => deflate { defined $_[1] && ref $_[1]
120             ? Email::Address->as_string
121             : $_[1] };
122              
123             has_one_namer { my $name = $_[0]->name();
124             my @parts = map { lc } ( $name =~ /([A-Z][a-z]+)/g );
125              
126             return join q{_}, @parts; };
127              
128             has_many_namer { my $name = $_[0]->name();
129             my @parts = map { lc } ( $name =~ /([A-Z][a-z]+)/g );
130              
131             $parts[-1] = PL_N( $parts[-1] );
132              
133             return join q{_}, @parts; };
134              
135             package User;
136              
137             use Fey::ORM::Table;
138              
139             has_policy 'MyApp::Policy';
140              
141             has_table ...;
142              
143             =head1 DESCRIPTION
144              
145             This module allows you to declare a policy for your
146             L<Fey::ORM::Table>-using classes.
147              
148             A policy can define transform rules which can be applied to matching
149             columns, as well as a naming scheme for has_one and has_many
150             methods. This allows you to spare yourself some drudgery, and allows
151             you to consolidate decisions (like "all date type columns return a
152             C<DateTime> object") in a single place.
153              
154             =head1 FUNCTIONS
155              
156             This module exports a bunch of sugar functions into your namespace so
157             you can define your policy in a declarative manner:
158              
159             =head2 transform_all
160              
161             This should be followed by a C<matching> sub reference, and one of an
162             C<inflate> or C<deflate> sub.
163              
164             =head2 matching { ... }
165              
166             This function takes a subroutine reference that will be called and
167             passed a L<Fey::Column> object as its argument. This sub should look
168             at the column and return true if the associated inflate/deflate should
169             be applied to the column.
170              
171             Note that the matching subs are checked in the order they are defined
172             by C<transform_all()>, and the first one wins.
173              
174             =head2 inflate { ... }
175              
176             An inflator sub for the associated transform. See L<Fey::ORM::Table>
177             for more details on transforms.
178              
179             =head2 deflate { ... }
180              
181             A deflator sub for the associated transform. See L<Fey::ORM::Table>
182             for more details on transforms.
183              
184             =head2 has_one_namer { ... }
185              
186             A subroutine reference which will be used to generate a name for
187             C<has_one()> methods when a name is not explicitly provided.
188              
189             This sub will receive the foreign table as its first argument, and the
190             associated FK object as the second argument. In most cases, the foreign table
191             will probably be sufficient to generate a name.
192              
193             =head2 has_many_namer { ... }
194              
195             Just like the C<has_one_namer()>, but is called for naming
196             C<has_many()> methods.
197              
198             =head2 Policy
199              
200             This methods returns the L<Fey::Object::Policy> object for your policy
201             class. This method allows L<Fey::ORM::Table> to go get a policy object
202             from a policy class name.
203              
204             =head1 AUTHOR
205              
206             Dave Rolsky <autarch@urth.org>
207              
208             =head1 COPYRIGHT AND LICENSE
209              
210             This software is copyright (c) 2011 - 2015 by Dave Rolsky.
211              
212             This is free software; you can redistribute it and/or modify it under
213             the same terms as the Perl 5 programming language system itself.
214              
215             =cut