]> git.decadent.org.uk Git - maypole.git/blob - lib/Maypole/Model/Base.pm
Refactored ->retrieve to fetch_objects
[maypole.git] / lib / Maypole / Model / Base.pm
1 package Maypole::Model::Base;
2
3 use Maypole::Constants;
4 use attributes ();
5
6 our %remember;
7
8 sub MODIFY_CODE_ATTRIBUTES { $remember{ $_[1] } = $_[2]; () }
9
10 sub FETCH_CODE_ATTRIBUTES { $remember{ $_[1] } }
11
12 sub process {
13     my ( $class, $r ) = @_;
14     my $method = $r->action;
15     return if $r->{template};    # Authentication has set this, we're done.
16
17     $r->{template} = $method;
18     $r->objects([ $class->fetch_objects($r) ]);
19     $class->$method( $r, $obj, @{ $r->{args} } );
20 }
21
22 sub list_columns {
23     shift->display_columns;
24 }
25
26 sub display_columns {
27     sort shift->columns;
28 }
29
30 =head1 NAME
31
32 Maypole::Model::Base - Base class for model classes
33
34 =head1 DESCRIPTION
35
36 This is the base class for Maypole data models. This is an abstract class
37 meant to define the interface, and can't be used directly.
38
39 =head2 process
40
41 This is the engine of this module. It populates all the relevant variables
42 and calls the requested action.
43
44 Anyone subclassing this for a different database abstraction mechanism
45 needs to provide the following methods:
46
47 =head2 setup_database
48
49     $model->setup_database($config, $namespace, @data)
50
51 Uses the user-defined data in C<@data> to specify a database- for
52 example, by passing in a DSN. The model class should open the database,
53 and create a class for each table in the database. These classes will
54 then be C<adopt>ed. It should also populate C<< $config->{tables} >> and
55 C<< $config->{classes} >> with the names of the classes and tables
56 respectively. The classes should be placed under the specified
57 namespace. For instance, C<beer> should be mapped to the class
58 C<BeerDB::Beer>.
59
60 =head2 class_of
61
62     $model->class_of($r, $table)
63
64 This maps between a table name and its associated class.
65
66 =head2 fetch_objects
67
68 This method should populate $r->objects from $r->{args}.
69
70 =head2 adopt
71
72 This is called on an model class representing a table and allows the
73 master model class to do any set-up required. 
74
75 =head2 columns
76
77 This is a list of all the columns in a table. You may also override
78 see also C<display_columns>
79
80 =head2 table
81
82 This is the name of the table.
83
84 =cut 
85
86 sub class_of       { die "This is an abstract method" }
87 sub setup_database { die "This is an abstract method" }
88 sub fetch_objects { die "This is an abstract method" }
89
90 =head2 Commands
91
92 =over
93
94 =item do_edit
95
96 If there is an object in C<$r-E<gt>objects>, then it should be edited
97 with the parameters in C<$r-E<gt>params>; otherwise, a new object should
98 be created with those parameters, and put back into C<$r-E<gt>objects>.
99 The template should be changed to C<view>, or C<edit> if there were any
100 errors. A hash of errors will be passed to the template.
101
102 =cut
103
104 sub do_edit { die "This is an abstract method" }
105
106 =item list
107
108 The C<list> method should fill C<< $r-> objects >> with all of the
109 objects in the class. You may want to page this using C<Data::Page> or
110 similar.
111
112 =item edit
113
114 Empty Action
115
116 =item view
117
118 Empty Action.
119
120
121 =back
122
123 =cut
124
125 sub list : Exported {
126     die "This is an abstract method";
127 }
128
129 sub view : Exported {
130 }
131
132 sub edit : Exported {
133 }
134
135 =pod
136
137 Also, see the exported commands in C<Maypole::Model::CDBI>.
138
139 =head1 Other overrides
140
141 Additionally, individual derived model classes may want to override the
142 following methods:
143
144 =head2 display_columns
145
146 Returns a list of columns to display in the model. by default returns
147 all columns in alphabetical order. Override this in base classes to
148 change ordering, or elect not to show columns.
149
150 =head2 list_columns
151
152 Same as display_columns, only for listings. Defaults to display_columns
153
154 =head2 column_names
155
156 Return a hash mapping column names with human-readable equivalents.
157
158 =cut
159
160 sub column_names {
161     my $class = shift;
162     map {
163         my $col = $_;
164         $col =~ s/_+(\w)?/ \U$1/g;
165         $_ => ucfirst $col
166     } $class->columns;
167 }
168
169 =head2 description
170
171 A description of the class to be passed to the template.
172
173 =cut
174
175 sub description { "A poorly defined class" }
176
177 =head2 is_public
178
179 should return true if a certain action is supported, or false otherwise. 
180 Defaults to checking if the sub has the :Exported attribute.
181
182 =cut
183
184 sub is_public {
185     my ( $self, $action ) = @_;
186     my $cv = $self->can($action);
187     return 0 unless $cv;
188     my $attrs = join " ", attributes::get($cv);
189     do {
190         warn "$action not exported" if Maypole->debug;
191         return 0;
192     } unless $attrs =~ /\bExported\b/i;
193     return 1;
194 }
195
196 =head2 related
197
198 This can go either in the master model class or in the individual
199 classes, and returns a list of has-many accessors. A brewery has many
200 beers, so C<BeerDB::Brewery> needs to return C<beers>.
201
202 =cut
203
204 sub related {
205 }
206
207 1;