File Coverage

blib/lib/Mixin/Historian.pm
Criterion Covered Total %
statement 32 32 100.0
branch 1 2 50.0
condition n/a
subroutine 12 12 100.0
pod 5 5 100.0
total 50 51 98.0


line stmt bran cond sub pod time code
1             package Mixin::Historian 0.102001;
2             # ABSTRACT: a mixin for recording history about objects
3              
4 1     1   82835 use Mixin::ExtraFields 0.008 ();
  1         15547  
  1         29  
5 1     1   8 use parent 'Mixin::ExtraFields';
  1         1  
  1         5  
6              
7 1     1   59 use strict;
  1         2  
  1         17  
8 1     1   5 use warnings;
  1         2  
  1         25  
9              
10 1     1   1044 use Sub::Exporter::ForMethods ();
  1         1647  
  1         43  
11              
12 1         5 use Sub::Exporter -setup => {
13             groups => {
14             history => \'gen_fields_group',
15             },
16             installer => Sub::Exporter::ForMethods::method_installer(),
17 1     1   6 };
  1         2  
18              
19             #pod =head1 SYNOPSIS
20             #pod
21             #pod package My::Object;
22             #pod use Mixin::Historian -history => {
23             #pod driver => {
24             #pod class => 'YourDriver',
25             #pod ...,
26             #pod },
27             #pod };
28             #pod
29             #pod # Later...
30             #pod my $object = My::Object->retrieve(1234);
31             #pod
32             #pod $object->add_history({
33             #pod type => 'lava damage',
34             #pod severity => 'very badly burned',
35             #pod volcano => 'Eyjafjallajokull',
36             #pod });
37             #pod
38             #pod =head1 DESCRIPTION
39             #pod
40             #pod Mixin::Historian is an application of Mixin::ExtraFields. If you're not
41             #pod familiar with it, you should read about it, both in L
42             #pod documentation|Mixin::ExtraFields> and in L
43             #pod Mixin::ExtraFields|http://advent.rjbs.manxome.org/2009-12-22.html>.
44             #pod
45             #pod Generally, it provides simple mechanism for write-only history. Importing the
46             #pod C<-history> group will get you the C method, which generally will
47             #pod accept one hashref with at least a C key. This will be passed along to
48             #pod the driver's C method.
49             #pod
50             #pod =head1 TODO
51             #pod
52             #pod I have shoehorned an extra layer of functionality into the Historian driver
53             #pod that I use in my employer's code. When initialized, the Historian mixin is
54             #pod told all legal types, something like this:
55             #pod
56             #pod type_map => {
57             #pod 'lava damage' => {
58             #pod severity => { required => 1, store_as => 'extra_1' },
59             #pod volcano => { required => 0, store_as => 'extra_2' },
60             #pod },
61             #pod ...
62             #pod }
63             #pod
64             #pod This way, history entries can be validated before writing. The C
65             #pod entries indicate how the arguments to C are mapped to database
66             #pod columns. The entire argument is also stored in one field as JSON, and a few
67             #pod other attributes are always required (like C) and some are added just
68             #pod in time (like C).
69             #pod
70             #pod This feature is not yet present in the CPAN library because I have not yet
71             #pod found a suitable decomposition of concerns to make it a component.
72             #pod
73             #pod =cut
74              
75 1     1 1 4 sub default_moniker { 'history' }
76              
77 1     1 1 204 sub driver_base_class { 'Mixin::Historian::Driver' }
78              
79 1     1 1 5 sub methods { qw(add) }
80              
81             sub driver_method_name {
82 1     1 1 2 my ($self, $method) = @_;
83 1         3 $self->method_name($method, 'history');
84             }
85              
86             sub build_method {
87 1     1 1 15 my ($self, $method_name, $arg) = @_;
88              
89             # Remember that these are all passed in as references, to avoid unneeded
90             # copying. -- rjbs, 2006-12-07
91 1         3 my $id_method = $arg->{id_method};
92 1         1 my $driver = $arg->{driver};
93              
94 1         3 my $driver_method = $self->driver_method_name($method_name);
95              
96             return sub {
97 2     2   704 my $object = shift;
98 2         8 my $id = $object->$$id_method;
99 2 50       13 Carp::confess "couldn't determine id for object" unless defined $id;
100 2         16 $$driver->$driver_method({
101             object => $object,
102             mixin => $self,
103             id => $id,
104             args => \@_,
105             });
106 1         11 };
107             }
108              
109             1;
110              
111             __END__