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