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