File Coverage

blib/lib/Jifty/DBI/Record/Plugin.pm
Criterion Covered Total %
statement 23 23 100.0
branch 3 6 50.0
condition n/a
subroutine 4 4 100.0
pod n/a
total 30 33 90.9


line stmt bran cond sub pod time code
1             package Jifty::DBI::Record::Plugin;
2              
3 1     1   738 use warnings;
  1         1  
  1         29  
4 1     1   3 use strict;
  1         1  
  1         22  
5              
6 1     1   3 use base qw/Exporter/;
  1         1  
  1         227  
7              
8             =head1 NAME
9              
10             Jifty::DBI::Record::Plugin - Record model mixins for Jifty::DBI
11              
12             =head1 SYNOPSIS
13              
14             # Define a mixin
15             package MyApp::FavoriteColor;
16             use base qw/ Jifty::DBI::Record::Plugin /;
17              
18             # Define which methods you want to put in the host model
19             our @EXPORT = qw(
20             favorite_complementary_color
21             );
22              
23             use Jifty::DBI::Schema;
24             use Jifty::DBI::Record schema {
25             column favorite_color =>
26             type is 'text',
27             label is 'Favorite Color',
28             valid_values are qw/ red green blue yellow /;
29             };
30              
31             sub favorite_complementary_color {
32             my $self = shift; # whatever host object thing we've mixed with
33             my $color = $self->favorite_color;
34             return $color eq 'red' ? 'green'
35             : $color eq 'green' ? 'red'
36             : $color eq 'blue' ? 'orange'
37             : $color eq 'yellow' ? 'purple'
38             : undef;
39             }
40              
41             # Use the mixin
42             package MyApp::Model::User;
43              
44             use Jifty::DBI::Schema;
45             use Jifty::DBI::Record schema {
46             column name =>
47             type is 'text',
48             label is 'Name';
49             };
50              
51             # Mixins
52             use MyApp::FavoriteColor;
53              
54             sub name_and_color {
55             my $self = shift;
56             my $name = $self->name;
57             my $color = $self->favorite_color;
58              
59             return "The favorite color of $name is $color.";
60             }
61              
62             sub name_and_complementary_color {
63             my $self = shift;
64             my $name = $self->name;
65             my $color = $self->favorite_complementary_color;
66              
67             return "The complement of $name's favorite color is $color.";
68             }
69              
70             =head1 DESCRIPTION
71              
72             By using this package you may provide models that are built from one or more mixins. In fact, your whole table could be defined in the mixins without a single column declared within the model class itself.
73              
74             =head2 MODEL MIXINS
75              
76             To build a mixin, just create a model that inherits from this package, C. Then, add the schema definitions you want inherited.
77              
78             package MyApp::FasterSwallow;
79             use base qw/ Jifty::DBI::Record::Plugin /;
80            
81             use Jifty::DBI::Schema;
82             use Jifty::DBI::Record schema {
83             column swallow_type =>
84             type is 'text',
85             valid are qw/ african european /,
86             default is 'african';
87             };
88              
89             =head3 @EXPORT
90              
91             A mixin may define an C<@EXPORT> variable, which works exactly as advertised in L. That is, given the name of any methods or variable names in the mixin, the host model will gain those methods.
92              
93             our @EXPORT = qw( autocomplete_swallow_type );
94              
95             sub autocomplete_swallow_type {
96             my $self = shift;
97             my $value = quotemeta(shift);
98              
99             # You should probably find a better way than actually doing this...
100              
101             my @values;
102             push @values, 'african' if 'african' =~ /$value/;
103             push @values, 'european' if 'european' =~ /$value/;
104              
105             return @values;
106             }
107              
108             That way if you have any custom methods you want to throw into the host model, just define them in the mixin and add them to the C<@EXPORT> variable.
109              
110             =head3 register_triggers
111              
112             Your mixin may also want to register triggers for the records to which it will be added. You can do this by defining a method named C:
113              
114             sub register_triggers {
115             my $self = shift;
116             $self->add_trigger(
117             name => 'before_create',
118             callback => \&before_create,
119             abortable => 1,
120             );
121             }
122              
123             sub before_create {
124             # do something...
125             }
126              
127             See L.
128              
129             =head3 register_triggers_for_column
130              
131             In addition to the general L method described above, the mixin may also implement a C method. This is called for each column in the table. This is primarily helpful for registering the C and C columns.
132              
133             For example:
134              
135             sub register_triggers_for_column {
136             my $self = shift;
137             my $column = shift;
138              
139             return unless $column ne 'updated_on';
140              
141             $self->add_trigger(
142             name => 'after_set_'.$column,
143             callback => \&touch_update_time,
144             abortable => 1,
145             );
146             }
147              
148             sub touch_update_time {
149             my $self = shift;
150             $self->set_updated_on(DateTime->now);
151             }
152              
153             This has the additional advantage of being callable when new columns are added to a table while the application is running. This can happen when using database-backed models in Jifty (which, as of this writing, has not been released or made part of the development trunk of Jifty, but is part of the virtual-models branch).
154              
155             See L.
156              
157             =head2 MODELS USING MIXINS
158              
159             To use your model plugin, just use the mixins you want to get columns from. You should still include a schema definition, even if it's empty:
160              
161             package MyApp::Model::User;
162              
163             use Jifty::DBI::Schema;
164             use MyApp::Record schema {
165             };
166              
167             # Mixins
168             use MyApp::FavoriteColor;
169             use MyApp::FasterSwallow;
170             use Jifty::Plugin::User::Mixin::Model::User;
171             use Jifty::Plugin::Authentication::Password::Mixin::Model::User;
172              
173             =cut
174              
175             sub import {
176 1     1   9 my $self = shift;
177 1         2 my $caller = caller;
178 1         6 for ($self->columns) {
179 1         24 $caller->_init_methods_for_column($_);
180 1 50       3 $caller->COLUMNS->{ $_->name } = $_ unless $_->virtual;
181             }
182 1         65 $self->export_to_level(1,undef);
183            
184 1 50       6 if (my $triggers = $self->can('register_triggers') ) {
185 1         2 $triggers->($caller)
186             }
187              
188 1 50       120 if (my $triggers_for_column = $self->can('register_triggers_for_column') ) {
189 1         3 for my $column (keys %{$caller->_columns_hashref}) {
  1         5  
190 5         196 $triggers_for_column->($caller, $column)
191             }
192             }
193              
194 1         44 push(@{ $caller->RECORD_MIXINS }, $self)
  1         5  
195             }
196              
197             =head1 SEE ALSO
198              
199             L, L
200              
201             =head1 LICENSE
202              
203             Jifty::DBI is Copyright 2005-2007 Best Practical Solutions, LLC.
204             Jifty is distributed under the same terms as Perl itself.
205              
206             =cut
207              
208             1;