added reference implementation of DBIx::Class::Manual::Example
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Manual / Example.pod
CommitLineData
3f341474 1=head1 NAME
2
3DBIx::Class::Manual::Example - Simple CD database example
4
5=head1 DESCRIPTION
6
880a1a0c 7This tutorial will guide you through the process of setting up and
3f341474 8testing a very basic CD database using SQLite, with DBIx::Class::Schema
9as the database frontend.
10
11The database consists of the following:
12
90efcf94 13 table 'artist' with columns: artistid, name
14 table 'cd' with columns: cdid, artist, title
15 table 'track' with columns: trackid, cd, title
3f341474 16
17
18And these rules exists:
19
90efcf94 20 one artist can have many cds
21 one cd belongs to one artist
22 one cd can have many tracks
23 one track belongs to one cd
3f341474 24
25
26=head2 Installation
27
28Install DBIx::Class via CPAN should be sufficient.
29
30=head3 Create the database/tables.
31
32First make and change the directory:
33
90efcf94 34 mkdir app
35 cd app
3f341474 36
37This example uses SQLite which is a dependency of DBIx::Class, so you
38shouldn't have to install extra software.
39
40Save the following into a example.sql
41
90efcf94 42 CREATE TABLE artist (
49e87fbb 43 artistid INTEGER PRIMARY KEY,
44 name TEXT NOT NULL
90efcf94 45 );
3f341474 46
90efcf94 47 CREATE TABLE cd (
49e87fbb 48 cdid INTEGER PRIMARY KEY,
49 artist INTEGER NOT NULL REFERENCES artist(artistid),
50 title TEXT NOT NULL
51 );
3f341474 52
90efcf94 53 CREATE TABLE track (
49e87fbb 54 trackid INTEGER PRIMARY KEY,
55 cd INTEGER NOT NULL REFERENCES cd(cdid),
56 title TEXT NOT NULL
57 );
3f341474 58
59and create the sqlite database file:
60
61sqlite3 example.db < example.sql
62
63=head3 Set up DBIx::Class::Schema
64
65First, create some dirs and change working directory:
66
90efcf94 67 mkdir MyDatabase
68 mkdir MyDatabase/Main
3f341474 69
70Then, create the following DBIx::Class::Schema classes:
71
72MyDatabase/Main.pm:
90efcf94 73
74 package MyDatabase::Main;
75 use base qw/DBIx::Class::Schema/;
76 __PACKAGE__->load_classes(qw/Artist Cd Track/);
3f341474 77
90efcf94 78 1;
3f341474 79
80
81MyDatabase/Main/Artist.pm:
82
90efcf94 83 package MyDatabase::Main::Artist;
84 use base qw/DBIx::Class/;
e8cc984c 85 __PACKAGE__->load_components(qw/PK::Auto Core/);
90efcf94 86 __PACKAGE__->table('artist');
87 __PACKAGE__->add_columns(qw/ artistid name /);
88 __PACKAGE__->set_primary_key('artistid');
89 __PACKAGE__->has_many('cds' => 'MyDatabase::Main::Cd');
3f341474 90
90efcf94 91 1;
3f341474 92
93
94MyDatabase/Main/Cd.pm:
95
90efcf94 96 package MyDatabase::Main::Cd;
97 use base qw/DBIx::Class/;
e8cc984c 98 __PACKAGE__->load_components(qw/PK::Auto Core/);
90efcf94 99 __PACKAGE__->table('cd');
100 __PACKAGE__->add_columns(qw/ cdid artist title/);
101 __PACKAGE__->set_primary_key('cdid');
102 __PACKAGE__->belongs_to('artist' => 'MyDatabase::Main::Artist');
103 __PACKAGE__->has_many('tracks' => 'MyDatabase::Main::Track');
3f341474 104
90efcf94 105 1;
3f341474 106
107
108MyDatabase/Main/Track.pm:
109
90efcf94 110 package MyDatabase::Main::Track;
111 use base qw/DBIx::Class/;
e8cc984c 112 __PACKAGE__->load_components(qw/PK::Auto Core/);
90efcf94 113 __PACKAGE__->table('track');
114 __PACKAGE__->add_columns(qw/ trackid cd title/);
115 __PACKAGE__->set_primary_key('trackid');
116 __PACKAGE__->belongs_to('cd' => 'MyDatabase::Main::Cd');
3f341474 117
90efcf94 118 1;
3f341474 119
120
121=head3 Write a script to insert some records.
122
123insertdb.pl
124
90efcf94 125 #!/usr/bin/perl -w
126
127 use MyDatabase::Main;
128 use strict;
129
130 my $schema = MyDatabase::Main->connect('dbi:SQLite:example.db');
131
132 # here's some of the sql that is going to be generated by the schema
133 # INSERT INTO artist VALUES (NULL,'Michael Jackson');
134 # INSERT INTO artist VALUES (NULL,'Eminem');
135
136 my @artists = (['Michael Jackson'], ['Eminem']);
137 $schema->populate('Artist', [
49e87fbb 138 [qw/name/],
139 @artists,
90efcf94 140 ]);
141
142 my %albums = (
49e87fbb 143 'Thriller' => 'Michael Jackson',
144 'Bad' => 'Michael Jackson',
145 'The Marshall Mathers LP' => 'Eminem',
146 );
90efcf94 147
148 my @cds;
149 foreach my $lp (keys %albums) {
49e87fbb 150 my $artist = $schema->resultset('Artist')->search({
151 name => $albums{$lp}
152 });
153 push @cds, [$lp, $artist->first];
90efcf94 154 }
155
156 $schema->populate('Cd', [
49e87fbb 157 [qw/title artist/],
158 @cds,
90efcf94 159 ]);
160
161
162 my %tracks = (
49e87fbb 163 'Beat It' => 'Thriller',
164 'Billie Jean' => 'Thriller',
165 'Dirty Diana' => 'Bad',
166 'Smooth Criminal' => 'Bad',
167 'Leave Me Alone' => 'Bad',
168 'Stan' => 'The Marshall Mathers LP',
169 'The Way I Am' => 'The Marshall Mathers LP',
90efcf94 170 );
171
172 my @tracks;
173 foreach my $track (keys %tracks) {
49e87fbb 174 my $cdname = $schema->resultset('Cd')->search({
175 title => $tracks{$track},
176 });
177 push @tracks, [$cdname->first, $track];
90efcf94 178 }
179
180 $schema->populate('Track',[
49e87fbb 181 [qw/cd title/],
182 @tracks,
90efcf94 183 ]);
3f341474 184
e8cc984c 185=head3 Create and run the test scripts
3f341474 186
187testdb.pl:
188
90efcf94 189 #!/usr/bin/perl -w
190
191 use MyDatabase::Main;
192 use strict;
193
194 my $schema = MyDatabase::Main->connect('dbi:SQLite:example.db');
e8cc984c 195 # for other DSNs, e.g. MySql, see the perldoc for the relevant dbd
196 # driver, e.g perldoc L<DBD::mysql>.
90efcf94 197
198 get_tracks_by_cd('Bad');
199 get_tracks_by_artist('Michael Jackson');
200
201 get_cd_by_track('Stan');
202 get_cds_by_artist('Michael Jackson');
203
204 get_artist_by_track('Dirty Diana');
205 get_artist_by_cd('The Marshall Mathers LP');
206
207
208 sub get_tracks_by_cd {
49e87fbb 209 my $cdtitle = shift;
210 print "get_tracks_by_cd($cdtitle):\n";
211 my $rs = $schema->resultset('Track')->search(
212 {
213 'cd.title' => $cdtitle
214 },
215 {
216 join => [qw/ cd /],
217 prefetch => [qw/ cd /]
90efcf94 218 }
49e87fbb 219 );
220 while (my $track = $rs->next) {
221 print $track->title . "\n";
222 }
223 print "\n";
90efcf94 224 }
225
226 sub get_tracks_by_artist {
49e87fbb 227 my $artistname = shift;
228 print "get_tracks_by_artist($artistname):\n";
229 my $rs = $schema->resultset('Track')->search(
230 {
231 'artist.name' => $artistname
232 },
233 {
234 join => {
235 'cd' => 'artist'
236 },
90efcf94 237 }
49e87fbb 238 );
239 while (my $track = $rs->next) {
240 print $track->title . "\n";
241 }
242 print "\n";
90efcf94 243 }
244
245
90efcf94 246 sub get_cd_by_track {
49e87fbb 247 my $tracktitle = shift;
248 print "get_cd_by_track($tracktitle):\n";
249 my $rs = $schema->resultset('Cd')->search(
250 {
251 'tracks.title' => $tracktitle
252 },
253 {
254 join => [qw/ tracks /],
255 }
256 );
257 my $cd = $rs->first;
258 print $cd->title . "\n\n";
90efcf94 259 }
260
261 sub get_cds_by_artist {
49e87fbb 262 my $artistname = shift;
263 print "get_cds_by_artist($artistname):\n";
264 my $rs = $schema->resultset('Cd')->search(
265 {
266 'artist.name' => $artistname
267 },
268 {
269 join => [qw/ artist /],
270 prefetch => [qw/ artist /]
90efcf94 271 }
49e87fbb 272 );
273 while (my $cd = $rs->next) {
274 print $cd->title . "\n";
275 }
276 print "\n";
90efcf94 277 }
278
279
280
281 sub get_artist_by_track {
49e87fbb 282 my $tracktitle = shift;
283 print "get_artist_by_track($tracktitle):\n";
284 my $rs = $schema->resultset('Artist')->search(
285 {
286 'tracks.title' => $tracktitle
287 },
288 {
289 join => {
290 'cds' => 'tracks'
291 }
292 }
293 );
294 my $artist = $rs->first;
295 print $artist->name . "\n\n";
90efcf94 296 }
297
298 sub get_artist_by_cd {
49e87fbb 299 my $cdtitle = shift;
300 print "get_artist_by_cd($cdtitle):\n";
301 my $rs = $schema->resultset('Artist')->search(
302 {
303 'cds.title' => $cdtitle
304 },
305 {
306 join => [qw/ cds /],
307 }
308 );
309 my $artist = $rs->first;
310 print $artist->name . "\n\n";
90efcf94 311 }
3f341474 312
313
314
315It should output:
316
90efcf94 317 get_tracks_by_cd(Bad):
318 Dirty Diana
319 Smooth Criminal
320 Leave Me Alone
3f341474 321
90efcf94 322 get_tracks_by_artist(Michael Jackson):
323 Beat it
324 Billie Jean
325 Dirty Diana
326 Smooth Criminal
327 Leave Me Alone
3f341474 328
90efcf94 329 get_cd_by_track(Stan):
330 The Marshall Mathers LP
3f341474 331
90efcf94 332 get_cds_by_artist(Michael Jackson):
333 Thriller
334 Bad
3f341474 335
90efcf94 336 get_artist_by_track(Dirty Diana):
337 Michael Jackson
3f341474 338
90efcf94 339 get_artist_by_cd(The Marshall Mathers LP):
340 Eminem
3f341474 341
342=head1 Notes
343
344With these scripts we're relying on @INC looking in the current
345working directory. You may want to add the MyDatabase namespaces to
880a1a0c 346@INC in a different way when it comes to deployment.
3f341474 347
348The testdb.pl script is an excellent start for testing your database
349model.
350
351=head1 TODO
352
353=head1 AUTHOR
354
355 sc_ from irc.perl.org#dbix-class
356 Kieren Diment <kd@totaldatasolution.com>
357
358=cut