fill in example classes
[dbsrgits/dbix-class-introduction-presentation.git] / slideshow.html
CommitLineData
52d980cb 1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
4<html xmlns="http://www.w3.org/1999/xhtml">
5
6<head>
7<title>DBIx::Class (aka DBIC)</title>
8<!-- metadata -->
9<meta name="contributor" content="youcan[64]netzgesta[46]de" />
10<meta name="publisher" content="s5.netzgesta.de" />
11<meta name="description" content="S5 1.3 is a very flexible and lightweight slide show system available for anyone to use (including transitions and scalable fonts and images)" />
12<meta name="keywords" content="S5, version 1.3, slide show, presentation-mode, projection-mode, powerpoint-like, scala-like, keynote-like, incremental display, scalable fonts, scalable images, transitions, notes, osf, xoxo, css, javascript, xhtml, public domain" />
13
14<meta name="generator" content="S5" />
15<meta name="version" content="1" />
16<meta name="subject" content="DBIx::Class" />
17<meta name="author" content="See first slide" />
18<meta name="company" content="N/A" />
19<meta name="robots" content="index, follow" />
20<meta name="revisit-after" content="7 days" />
21<!-- meta additionally -->
22<meta http-equiv="content-type" content="text/html; charset=utf-8" />
23<meta http-equiv="Content-Script-Type" content="text/javascript" />
24<meta http-equiv="Content-Style-Type" content="text/css" /><!-- configuration parameters -->
25<meta name="defaultView" content="slideshow" />
26<meta name="controlVis" content="hidden" />
27<!-- configuration transition extension -->
28<meta name="tranSitions" content="true" />
29<meta name="fadeDuration" content="500" />
30<meta name="incrDuration" content="250" />
31<!-- configuration autoplay extension -->
32<meta name="autoMatic" content="false" />
33<meta name="playLoop" content="true" />
34<meta name="playDelay" content="10" />
35<!-- configuration audio extension -->
36<meta name="audioSupport" content="false" />
37<meta name="audioVolume" content="0" />
38<meta name="audioError" content="false" />
39<!-- configuration audio debug -->
40<meta name="audioDebug" content="false" />
41<!-- style sheet links -->
42<link rel="stylesheet" href="ui/scala_utf/slides.css" type="text/css" media="projection" id="slideProj" />
43<link rel="stylesheet" href="ui/scala_utf/outline.css" type="text/css" media="screen" id="outlineStyle" />
44<link rel="stylesheet" href="ui/scala_utf/print.css" type="text/css" media="print" id="slidePrint" />
45<link rel="stylesheet" href="ui/scala_utf/opera.css" type="text/css" media="projection" id="operaFix" />
46<!-- embedded styles -->
47<style type="text/css" media="all">
48.imgcon {width: 100%; margin: 0 auto; padding: 0; text-align: center;}
49#anim {width: 33%; height: 320px; position: relative;}
50#anim img {position: absolute; top: 0px; left: 0px;}
51.red {color: red;}
52.grey {color: gray;}
53</style>
54<!-- S5 JS -->
55<script src="ui/scala_utf/slides.js" type="text/javascript"></script>
56</head>
57<body>
58
59<div class="layout">
60 <div id="controls"><!-- DO NOT EDIT --></div>
61 <div id="currentSlide"><!-- DO NOT EDIT --></div>
62 <div id="header"></div>
63 <div id="footer">
64 <h1>DBIx::Class Introduction</h1>
65 <h2>YAPC::NA 2010</h2>
66 </div>
67</div>
68
69<div class="presentation">
70
71 <div class="slide">
72 <h1>DBIX::Class (aka DBIC)</h1>
73 <h3>for (advanced) beginners</h3>
0cffcad7 74 </div>
75
76 <div class="slide">
77 <h1>Authors</h1>
78 <h4>Originally Leo Lapworth @ LPW 2009</h4>
79 <h4>Matthew S. Trout</h4>
0cffcad7 80 <h4>Justin D. Hunter</h4>
5cac74c7 81 <h4>Arthur Axel "fREW" Schmidt</h4>
52d980cb 82 </div>
83
84 <div class="slide">
85 <h1>assumptions</h1>
86 <p>You know a little about Perl and using objects</p>
87 <p>You know a little bit about databases and using foreign keys</p>
0cffcad7 88 <div class="notes">
89 <ul>
90 <li>How many people have designed a database with Foreign Keys?</li>
91 <li>How many people have used any ORM?<ul>
92 <li>In Perl?<ul>
93 <li>DBIC?</li>
94 <li> Class::DBI? </li>
95 <li> Rose::DB? </li>
96 <li> Fey? </li>
97 <li> Others? </li>
98 </ul></li>
99 <li>AR? </li>
100 <li> DataMapper? </li>
101 <li>(N)Hibernate?</li>
102 </ul></li>
103 </ul>
104 </div>
52d980cb 105 </div>
106
107 <div class="slide">
108 <h1>DBIx::Class?</h1>
109 <ul>
110 <li>ORM (object relational mapper)</li>
111 <li>SQL &lt;-&gt; OO (using objects instead of SQL)</li>
112 <li>Simple, powerful, complex, fab and confusing</li>
113 <li>There are many ORMs, DBIx::Class just happens to be the best in Perl (personal opinion)</li>
114 </ul>
115 </div>
116
117 <div class="slide">
52d980cb 118 <h1>point of note</h1>
5cac74c7 119 <p><em>"Debugging is twice as hard as writing the code in the first
120 place. Therefore, if you write the code as cleverly as possible,
121 you are, by definition, not smart enough to debug it." - Brian
122 W. Kernighan</em></p>
52d980cb 123
5cac74c7 124 <p>This talk is about making it easy so we are less likely to get
125 confused</p>
52d980cb 126 </div>
127
128 <div class="slide">
5cac74c7 129 <h1>Examples Table Setup</h1>
52d980cb 130 <ul>
131 <li>Authors</li>
132 <li>Books</li>
133 </ul>
5cac74c7 134 <em>MySQL not recommended</em>
52d980cb 135 </div>
136
137 <div class="slide">
138 <h1>authors table</h1>
139<pre>CREATE TABLE authors(
140 id int(8) primary key auto_increment,
141 name varchar(255)
142) engine = InnoDB DEFAULT CHARSET=utf8;</pre>
143 </div>
144
145 <div class="slide">
146 <h1>tips</h1>
147 <p>Name tables as simple plurals (<strong>add an S</strong>) - makes relationships easier to understand</p>
52d980cb 148 <p>Use a character set (<strong>UTF8</strong>) from the start (for international characters)</p>
149 </div>
150
151 <div class="slide">
152 <h1>authors table</h1>
153<pre>CREATE TABLE author<strong>s</strong>(
154 id int(8) primary key auto_increment,
155 name varchar(255)
156) engine = <strong>InnoDB</strong> DEFAULT CHARSET=<strong>utf8</strong>;</pre>
157 </div>
158
159 <div class="slide">
160 <h1>books table</h1>
161<pre>CREATE TABLE books(
5cac74c7 162 id int(8) primary key auto_increment,
163 title varchar(255),
164 author_id int(8),foreign key (author)
52d980cb 165 references authors(id)
166) engine = InnoDB DEFAULT CHARSET=utf8;</pre>
167 </div>
168
169
170 <div class="slide">
171 <h1>tips</h1>
172 <p>Name link fields as singular</p>
5cac74c7 173 <p>Ensure foreign key is the same type and size in both tables</p>
52d980cb 174 </div>
175
176 <div class="slide">
177 <h1>books table</h1>
178<pre>CREATE TABLE books(
5cac74c7 179 id int(8) primary key auto_increment,
180 title varchar(255),
181 author_id <strong>int(8)</strong>,<strong>foreign key (<em>author</em>)</strong>
52d980cb 182 <strong>references <em>authors(id)</em></strong>
183) engine = InnoDB DEFAULT CHARSET=utf8;</pre>
184 </div>
185
186 <div class="slide">
187 <h1>CRUD compared</h1>
188 <ul>
189 <li><strong>C</strong> - Create</li>
190 <li><strong>R</strong> - Read</li>
191 <li><strong>U</strong> - Update</li>
192 <li><strong>D</strong> - Delete</li>
193 </ul>
194 </div>
195
196 <div class="slide">
197 <h1>Manual (SQL)</h1>
198 </div>
199
200 <div class="slide">
5cac74c7 201 <h1>SQL: Create</h1>
52d980cb 202<pre>my $sth = $dbh-&gt;prepare('
203 INSERT INTO books
204 (title, author)
205 values (?,?)
206');
207
208$sth-&gt;execute(
209 'A book title', $author_id
210);</pre>
211 </div>
212
213 <div class="slide">
5cac74c7 214 <h1>SQL: Read</h1>
52d980cb 215<pre>my $sth = $dbh-&gt;prepare('
216 SELECT title,
217 authors.name as author_name
218 FROM books, authors
219 WHERE books.author = authors.id
220');</pre>
221 </div>
222
223 <div class="slide">
5cac74c7 224 <h1>SQL: Read</h1>
52d980cb 225<pre>while( my $book = $sth-&gt;fetchrow_hashref() ) {
226 print 'Author of '
227 . $book-&gt;{title}
228 . ' is '
229 . $book-&gt;{author_name}
230 . "\n";
231}</pre>
232 </div>
233
234 <div class="slide">
5cac74c7 235 <h1>SQL: Update</h1>
52d980cb 236<pre>my $update = $dbh-&gt;prepare('
237 UPDATE books
238 SET title = ?
239 WHERE id = ?
240');
241
242$update-&gt;execute(
243 'New title',<strong>$book_id</strong>
244);</pre>
245 </div>
246
247 <div class="slide">
5cac74c7 248 <h1>SQL: Delete</h1>
52d980cb 249<pre>my $delete = $dbh-&gt;prepare('
250 DELETE FROM books
251 WHERE id = ?
252');
253
254$delete-&gt;execute(<strong>$book_id</strong>);</pre>
255 </div>
256
257 <div class="slide">
258 <h1>DBIx::Class</h1>
259 </div>
260
261 <div class="slide">
5cac74c7 262 <h1>DBIC: Create</h1>
52d980cb 263<pre>my $book = $book_model-&gt;create({
264 title =&gt; 'A book title',
265 author =&gt; $author_id,
266});</pre>
267 <p>Look ma, no SQL!</p>
52d980cb 268 </div>
269
270 <div class="slide">
5cac74c7 271 <h1>DBIC: Create</h1>
52d980cb 272<pre>my $pratchett = $author_model-&gt;create({
273 name =&gt; 'Terry Pratchett',
274});</pre>
275 </div>
276
277 <div class="slide">
5cac74c7 278 <h1>DBIC: Create</h1>
52d980cb 279<pre>my $book = $pratchett-&gt;create_related(
280 <strong>books</strong> =&gt; {
281 title =&gt; 'Another Discworld book',
282});</pre>
283<strong>or</strong>
284<pre>my $book = $pratchett-&gt;add_to_<strong>books</strong>({
285 title =&gt; 'Another Discworld book',
286});</pre>
287 </div>
288
289 <div class="slide">
5cac74c7 290 <h1>DBIC: Read</h1>
52d980cb 291 <p>DBIx::Class - Lots of ways to do the same thing...</p>
292 <p><em>"There is more than one way to do it (TIMTOWTDI, usually pronounced "Tim Toady") is a Perl motto"</em></p>
293 </div>
294
295 <div class="slide">
5cac74c7 296 <h1>DBIC: Read</h1>
52d980cb 297<pre>my $book = $book_model-&gt;find($book_id);
298
299my $book = $book_model-&gt;search({
300 title =&gt; 'A book title',
5cac74c7 301}, { rows =&gt; 1 })-&gt;single;
52d980cb 302
303my @books = $book_model-&gt;search({
304 author =&gt; $author_id,
305})-&gt;all;</pre>
306 </div>
307
308 <div class="slide">
5cac74c7 309 <h1>DBIC: Read</h1>
310<pre>while( my $book = $books_rs-&gt;next ) {
52d980cb 311 print 'Author of '
312 . $book-&gt;title
313 . ' is '
314 . $book-&gt;author-&gt;name
315 . "\n";
316}</pre>
317 </div>
318
319 <div class="slide">
5cac74c7 320 <h1>DBIC: Read</h1>
321<pre>my $books_rs = $book_rs-&gt;search({
52d980cb 322 author =&gt; $author_id,
323});</pre>
324 <p>Search takes SQL::Abstract formatted queries</p>
325 <pre>&gt; perldoc SQL::Abstract</p>
326 </div>
327
328 <div class="slide">
5cac74c7 329 <h1>DBIC: Update</h1>
52d980cb 330<pre>$book-&gt;update({
331 title =&gt; 'New title',
332});</pre>
333 </div>
334
335 <div class="slide">
5cac74c7 336 <h1>DBIC: Delete</h1>
52d980cb 337<pre>$book-&gt;delete;</pre>
338 </div>
339
340 <div class="slide">
341 <h1>Creating models</h1>
342 </div>
343
344 <div class="slide">
492be2ae 345<pre>package MyApp::Schema::Result::Author;
346use strict; use warnings;
347__PACKAGE__-&gt;table('authors');
348__PACKAGE__-&gt;add_columns(
349 id =&gt; {
350 data_type =&gt; 'int',
351 size =&gt; 8,
352 },
353 title =&gt; {
354 data_type =&gt; 'varchar',
355 is_nullable =&gt; 1,
356 size =&gt; 255,
357 },
358);
359__PACKAGE__-&gt;set_primary_key('id');
360__PACKAGE__-&gt;has_many( books =&gt;
361 'MyApp::Schema::Result::Book', 'author_id'
362);
3631;
364</pre>
365 </div>
366
367 <div class="slide">
368<pre>package MyApp::Schema::Result::Book;
369use strict; use warnings;
370__PACKAGE__-&gt;table('books');
371__PACKAGE__-&gt;add_columns(
372 id =&gt; {
373 data_type =&gt; 'int',
374 size =&gt; 8,
375 },
376 name =&gt; {
377 data_type =&gt; 'varchar',
378 is_nullable =&gt; 1,
379 size =&gt; 255,
380 },
381 author_id =&gt; {
382 data_type =&gt; 'int',
383 size =&gt; 8,
384 is_nullable =&gt; 1, # &lt;-- probably should be 0
385 },
386);
387__PACKAGE__-&gt;set_primary_key('id');
388__PACKAGE__-&gt;belongs_to( author =&gt;
389 'MyApp::Schema::Result::Author', 'author_id'
390);
3911;
392</pre>
52d980cb 393 </div>
394
395 <div class="slide">
396 <p>too much typing! too much maintenance!</p>
52d980cb 397 </div>
398
399 <div class="slide">
400 <h1>Schema::Loader</h1>
401 <pre>code for S::L here</pre>
402 </div>
403
404 <div class="slide">
405 <h1>splitting logic cleanly</h1>
41a0eb8e 406 <p>Foo::Schema::Result::Foo = an individual row</p>
407 <p>Foo::Schema::ResultSet::Foo = searches / results</p>
52d980cb 408 </div>
409
410 <div class="slide">
411 <h1>using your Schema</h1>
412 <pre>example usage code goes here</pre>
413 </div>
414
415 <div class="slide">
416 <h1>DEBUGGING</h1>
417 <pre>DBIC_TRACE=1 ./your_script.pl</pre>
418 </div>
419
420 <div class="slide">
421 <h1>Schema::Loader</h1>
41a0eb8e 422<pre>Foo::Schema::Result::Authors-&gt;table("authors");
423Foo::Schema::Result::Authors-&gt;add_columns(
52d980cb 424 id =&gt; {
425 data_type =&gt; "INT",
426 default_value =&gt; undef,
427 is_nullable =&gt; 0,
428 size =&gt; 8
429 },
430 title =&gt; {
431 data_type =&gt; "VARCHAR",
432 default_value =&gt; undef,
433 is_nullable =&gt; 1,
434 size =&gt; 255,
435 },
436);
41a0eb8e 437Foo::Schema::Result::Authors-&gt;set_primary_key("id");</pre>
52d980cb 438 </div>
439
440 <div class="slide">
441 <h1>Schema::Loader</h1>
41a0eb8e 442<pre>Foo::Schema::Result::Books->table("books");
443Foo::Schema::Result::Books->add_columns(
52d980cb 444 id =&gt; {
445 data_type =&gt; "INT",
446 default_value =&gt; undef,
447 is_nullable =&gt; 0,
448 size =&gt; 8
449 },
450 name =&gt; {
451 data_type =&gt; "VARCHAR",
452 default_value =&gt; undef,
453 is_nullable =&gt; 1,
454 size =&gt; 255,
455 },
456 author =&gt; {
457 data_type =&gt; "INT",
458 default_value =&gt; undef,
459 is_nullable =&gt; 1,
460 size =&gt; 8
461 },
462);
41a0eb8e 463Foo::Schema::Result::Books-&gt;set_primary_key("id");</pre>
52d980cb 464 </div>
465
466 <div class="slide">
467 <h1>Schema::Loader</h1>
41a0eb8e 468<pre>Foo::Schema::Result::Authors-&gt;has_many(books =&gt; "Foo::Schema::Books",
52d980cb 469 { "foreign.author" =&gt; "self.id" });
470
41a0eb8e 471Foo::Schema::Result::Books-&gt;belongs_to(author =&gt; "Foo::Schema::Authors",
52d980cb 472 { id =&gt; "author" });</pre>
473 </div>
474
475 <div class="slide">
476 <h1>SQL - debugging</h1>
477<pre>INSERT INTO authors (name)
478 VALUES (?): 'Douglas Adams'
479
480INSERT INTO books (author, title)
481 VALUES (?, ?): '5', '42'</pre>
482 </div>
483
484 <div class="slide">
485 <h1>overloading</h1>
41a0eb8e 486<pre>Foo::Schema::Result::Books
487Foo::Schema::ResultSet::Books
488Foo::Schema::Result::Authors
489Foo::Schema::ResultSet::Books</pre>
52d980cb 490 </div>
491
492 <div class="slide">
493 <h1>Result::</h1>
41a0eb8e 494<pre>package Foo::Schema::Result::Books;
52d980cb 495use base 'DBIx::Class';
496use strict;
497use warnings;
498
499sub isbn {
500 my $self = shift;
501
502 # search amazon or something
503 my $api = Amazon::API-&gt;book({
504 title =&gt; $self-&gt;title
505 });
506
507 return $api-&gt;isbn;
508}
509
5101;</pre>
511 </div>
512
513 <div class="slide">
514 <h1>Result::</h1>
515<pre>print $book-&gt;isbn;</pre>
516 </div>
517
518 <div class="slide">
519 <h1>Result:: (inflating)</h1>
41a0eb8e 520<pre>package Foo::Schema::Result::Books;
52d980cb 521use base 'DBIx::Class';
522use strict;
523use warnings;
524
525use DateTime::Format::MySQL;
526
527__PACKAGE__-&gt;<strong>inflate_column</strong>(
528 <strong>date_published</strong> =&gt; {
529 inflate =&gt; sub { DateTime::Format::MySQL-&gt;parse_date(shift) },
530 deflate =&gt; sub { shift-&gt;ymd},
531 }
532);
533# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
534 </div>
535
536 <div class="slide">
537 <h1>Result:: (inflating)</h1>
41a0eb8e 538<pre>package Foo::Schema::Result::Books;
52d980cb 539use base 'DBIx::Class';
540use strict;
541use warnings;
542
543use DateTime::Format::MySQL;
544
545__PACKAGE__-&gt;inflate_column(
546 date_published =&gt; {
547 <strong>inflate =&gt; sub { DateTime::Format::MySQL-&gt;parse_date(shift) },
548 deflate =&gt; sub { shift-&gt;ymd},</strong>
549 }
550);
551# Automatic see: DBIx::Class::InflateColumn::DateTime
552# Automatic see: DBIx::Class::InflateColumn::DateTime
553# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
554 </div>
555
556 <div class="slide">
557 <h1>Result:: (deflating)</h1>
558<pre>$book-&gt;date_published(DateTime-&gt;now);
559$book-&gt;update;</pre>
560 </div>
561
562 <div class="slide">
563 <h1>Result:: (inflating)</h1>
564<pre>my $date_published = $book-&gt;date_published;
565print $date_published-&gt;month_abbr;</pre>
566
567<strong><em>Nov</em></strong>
568 </div>
569
570 <div class="slide">
571 <h1>ResultSets::</h1>
41a0eb8e 572<pre>package Foo::Schema::ResultSet::Books;
52d980cb 573use base 'DBIx::Class::ResultSet';
574sub the_ultimate_books {
575 my $self = shift;
576 return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } });
577}
578sub by_author {
579 my ( $self, $author ) = @_;
580 return $self-&gt;search({ author =&gt; $author-&gt;id })
581}
582
5831;</pre>
584 </div>
585
586 <div class="slide">
587 <h1>ResultSets::</h1>
41a0eb8e 588<pre>package Foo::Schema::<strong>ResultSet::Books</strong>;
52d980cb 589use base '<strong>DBIx::Class::ResultSet</strong>';
590sub the_ultimate_books {
591 my $self = shift;
592 <strong>return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } })</strong>
593}
594sub by_author {
595 my ( $self, $author ) = @_;
596 return $self-&gt;search({ author =&gt; $author-&gt;id })
597}
598
5991;</pre>
600 </div>
601
602 <div class="slide">
603 <h1>ResultSets::</h1>
41a0eb8e 604<pre>package Foo::Schema::ResultSet::Books;
52d980cb 605use base 'DBIx::Class::ResultSet';
606sub the_ultimate_books {
607 my $self = shift;
608 return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } });
609}
610sub by_author {
611 my ( $self, $author ) = @_;
612 <strong>return $self-&gt;search({ author =&gt; $author-&gt;id })</strong>
613}
614
6151;</pre>
616 </div>
617
618 <div class="slide">
619 <h1>ResultSets::</h1>
41a0eb8e 620<pre>use Foo::Schema;
621my $book_model = Foo::Schema-&gt;resultset('Books');
52d980cb 622my $book_rs = $book_model-&gt;the_ultimate_books;
623my @books = $book_rs-&gt;all;</pre>
624 </div>
625
626 <div class="slide">
627 <h1>ResultSets::chaining</h1>
41a0eb8e 628<pre>use Foo::Schema;
629my $book_model = Foo::Schema-&gt;resultset('Books');
630my $author_model = Foo::Schema-&gt;resultset('Authors');
52d980cb 631my $author = $author_model-&gt;search({ name =&gt; 'Douglas Adams' })-&gt;single;
632my $book_rs = $book_model-&gt;the_ultimate_books-&gt;by_author($author);
633my @books = $book_rs-&gt;all;</pre>
634 </div>
635
636 <div class="slide">
637 <h1>ResultSets::chaining</h1>
638<pre>my $book_rs = $book_model
639 -&gt;the_ultimate_books
640 -&gt;by_author($author);</pre>
641or
642
643<pre>my $book_rs = $book_model
644 -&gt;the_ultimate_books();
645$book_rs = $book_rs-&gt;by_author($author);</pre>
646<pre># Debug (SQL):
647
648# SELECT me.id, me.title, me.date_published, me.author
649# FROM books me
650# WHERE ( ( ( author = ? ) AND ( title LIKE ? ) ) ): '5', '%42%'
651# WHERE ( ( ( author = ? ) AND ( title LIKE ? ) ) ): '5', '%42%'</pre>
652 </div>
653
654 <div class="slide">
655 <h1>ResultSets::chaining</h1>
656<pre>my $rs = $book_model
657 -&gt;category('childrens')
658 -&gt;by_author($author)
659 -&gt;published_after('1812')
660 -&gt;first_page_contains('once upon')
661 -&gt;rating_greater_than(4);
662
663my @books = $rs-&gt;all;</pre>
664 </div>
665
666 <div class="slide">
667 <h1>overloading before new record</h1>
668 </div>
669
670 <div class="slide">
671 <h1>overloading before new record</h1>
41a0eb8e 672 <pre>package Foo::Schema::Result::Authors;
52d980cb 673use base 'DBIx::Class';
674
675sub new {
676 my ( $class, $attrs ) = @_;
677 # Mess with $attrs
678 my $new = $class-&gt;next::method($attrs);
679 return $new
680}
681
6821;</pre>
683
684 <div class="slide">
685 <h1>relationships</h1>
686 </div>
687
688 <div class="slide">
689 <h1>multiple authors</h1>
690 </div>
691
692 <div class="slide">
693 <h1>a few relationships</h1>
694 (authors -- author_link_to_book -- books)
695 </div>
696
697 <div class="slide">
698 <h1>a few relationships</h1>
699 !
700 </div>
701
702 <div class="slide">
703 <h1>new join table</h1>
704<pre>CREATE TABLE author_and_books(
705 id int(8) primary key auto_increment,
706 book int(8),
707 author int(8),
708 foreign key (book) references books(id),
709 foreign key (author) references authors(id)
710) engine = InnoDB DEFAULT CHARSET=utf8;
711
712ALTER TABLE `books` DROP `author`</pre>
713 </div>
714
715 <div class="slide">
716 <h1>new join table</h1>
717<pre>CREATE TABLE author_and_books(
718 id int(8) primary key auto_increment,
719 book int(8),
720 author int(8),
721 <strong>foreign key (book) references books(id),
722 foreign key (author) references authors(id)</strong>
723) engine = InnoDB DEFAULT CHARSET=utf8;
724
725ALTER TABLE `books` DROP `author`</pre>
726 </div>
727
728 <div class="slide">
729 <h1>has_many</h1>
730 </div>
731
732 <div class="slide">
733 <h1>has_many</h1>
41a0eb8e 734<pre>package Foo::Schema::<strong>Result::Books</strong>;
52d980cb 735
41a0eb8e 736__PACKAGE__-&gt;has_many( author_and_books =&gt; "Foo::Schema::Result::AuthorAndBooks",
52d980cb 737 { "foreign.book" =&gt; "self.id" },
738);
739
740<strong># This is auto generated by Schema::Loader</strong></pre>
741 </div>
742
743 <div class="slide">
744 <h1>has_many</h1>
41a0eb8e 745<pre>package Foo::Schema::<strong>Result::Books</strong>;
52d980cb 746
747__PACKAGE__-&gt;has_many(
748author_and_books =&gt; <strong># name of accessor</strong>
41a0eb8e 749"Foo::Schema::Result::AuthorAndBooks", <strong># related class</strong>
52d980cb 750 { "foreign.book" =&gt; "self.id" } <strong># Relationship (magic often works if not
751 # specified, but avoid!)</strong>
752);
753</pre>
754 </div>
755
756 <div class="slide">
757 <h1>belongs_to</h1>
758 </div>
759
760 <div class="slide">
761 <h1>belongs_to</h1>
41a0eb8e 762<pre>package Foo::Schema::<strong>Result::AuthorAndBooks</strong>;
52d980cb 763
764__PACKAGE__-&gt;belongs_to(
765 book =&gt; <strong># Accessor name</strong>
41a0eb8e 766 "Foo::Schema::Result::Books", <strong># Related class</strong>
52d980cb 767 { id =&gt; "book" } <strong># relationship</strong>
768);
769</pre>
770 </div>
771
772 <div class="slide">
773 <h1>same for Authors</h1>
774 </div>
775
776 <div class="slide">
777 <h1>with no coding...</h1>
778 </div>
779
780 <div class="slide">
781 <h1>many_to_many</h1>
782 </div>
783
784 <div class="slide">
785 <h1>many_to_many</h1>
41a0eb8e 786 <pre>package Foo::Schema::<strong>Result::Books</strong>;
52d980cb 787use base 'DBIx::Class';
788
789__PACKAGE__-&gt;many_to_many(
790 authors =&gt; "author_and_books", 'author'
791);
792
7931;
794
795<strong> # This is <em>NOT</em> auto generated by Schema::Loader </strong></pre>
796 </div>
797
798 <div class="slide">
799 <h1>many_to_many</h1>
41a0eb8e 800 <pre>package Foo::Schema::<strong>Result::Books</strong>;
52d980cb 801use base 'DBIx::Class';
802
803__PACKAGE__-&gt;many_to_many(
804 authors <strong># Accessor name</strong>
805 =&gt; "author_and_books", <strong># has_many</strong>
806 'author' <strong># foreign relationship name</strong>
807);
808
8091;</pre>
810 </div>
811
812 <div class="slide">
813 <h1>many_to_many</h1>
41a0eb8e 814 <pre>package Foo::Schema::Result::Authors;
52d980cb 815use base 'DBIx::Class';
816
817__PACKAGE__-&gt;many_to_many(
818 "books" <strong># Accessor Name</strong>
819 =&gt; "author_and_books", <strong># has_many accessor_name</strong>
820 'book' <strong># foreign relationship name</strong>
821);
822
8231;
824
825<strong># This is <em>NOT</em> auto generated by Schema::Loader</strong></pre>
826 </div>
827
828 <div class="slide">
829 <h1>using many_to_many</h1>
830 <pre>#!/usr/bin/perl
831
41a0eb8e 832use Foo::Schema;
52d980cb 833
41a0eb8e 834my $author_model = Foo::Schema-&gt;resultset('Authors');
52d980cb 835my $author = $author_model-&gt;search({
836 name =&gt; 'Douglas Adams',
837})-&gt;single;
838$author-&gt;add_to_books({
839 title =&gt; 'A new book',
840});</pre>
841 </div>
842
843 <div class="slide">
844 <h1>using many_to_many</h1>
845 <pre>my $author = $author_model-&gt;search({
846 name =&gt; 'Douglas Adams',
847})-&gt;single;
848<strong>$author-&gt;add_to_books({
849 title =&gt; 'A new book',
850});</strong>
851
852# SELECT me.id, me.name FROM authors me
853# WHERE ( name = ? ): 'Douglas Adams';
854# INSERT INTO books (title) VALUES (?): 'A new book';
855# INSERT INTO author_and_books (author, book)
856# VALUES (?, ?): '5', '2';</pre>
857 </div>
858
859 <div class="slide">
860 <h1>using many_to_many</h1>
861 <pre>$author-&gt;add_to_books($book);
862
863$book-&gt;add_to_authors($author_1);
864$book-&gt;add_to_authors($author_2);</pre>
865 </div>
866
867 <div class="slide">
868 <h1>in 16 lines of code</h1>
869 </div>
870
871 <div class="slide">
872 <h1>errors</h1>
873 <p>Read them closely!</p>
874 </div>
875
876 <div class="slide">
877 <h1>error messages</h1>
41a0eb8e 878 <pre>DBIx::Class::Schema::Loader::connection(): Failed to load external class definition for 'Foo::Schema::Result::Authors': Can't locate object method "many_to_many" via package "Foo::Schema::Result::Author" at lib/Foo/Schema/Result/Authors.pm line 9.Compilation failed in require at /Library/Perl/5.8.8/DBIx/Class/Schema/Loader/Base.pm line 292.</pre>
52d980cb 879 </div>
880
881 <div class="slide">
882 <h1>error messages</h1>
41a0eb8e 883 <pre>DBIx::Class::Schema::Loader::connection(): Failed to load external class definition for 'Foo::Schema::Result::Authors': Can't locate object method "many_to_many" via package "Foo::Schema::<strong>Result::Author</strong>" at lib/Foo/Schema/<strong>Result/Authors.pm</strong> line 9.Compilation failed in require at /Library/Perl/5.8.8/DBIx/Class/Schema/Loader/Base.pm line 292.</pre>
52d980cb 884 </div>
885
886 <div class="slide">
887 <h1>errors</h1>
888 <ul>
889 <li>Turn on debugging</li>
890 <li>Read error messages (sometimes useful!)</li>
891 <li>Check field names</li>
892 <li>Check package names</li>
893 <li>Check which database you are connected to (dev/test/live?) - repeat above</li>
894 </ul>
895 </div>
896
897 <div class="slide">
898 <h1>bonus slides!</h1>
899 </div>
900
901 <div class="slide">
902 <h1>Template Toolkit</h1>
903 <ul>
904 <li><pre>[% author.books.count %]</pre> not working?</li>
905 <li>TT all methods are called in list context</li>
906 <li><pre>[% author.books<strong>_rs</strong>.count %]</pre> scalar context</li>
907 <li><em>Available for all relationships</em></li>
908 </ul>
909 </div>
910
911 <div class="slide">
912 <h1>Catalyst</h1>
0cffcad7 913 <pre>package Your::App::Model::<strong>Foo</strong>;
41a0eb8e 914use base qw(<strong>Catalyst::Model::Schema::Schema</strong>);
52d980cb 915
916use strict;
917use warnings;
918
919__PACKAGE__-&gt;config(
41a0eb8e 920 schema_class =&gt; '<strong>Foo::Schema</strong>',
52d980cb 921);
922
9231;</pre>
924 <p>Keep your Schema in a <em>separate</em> package to your Catalyst application</p>
925 </div>
926
927 <div class="slide">
928 <h1>Catalyst</h1>
929<pre>sub action_name : Local {
930 my ($self, $c) = @_;
931
41a0eb8e 932 my $model = $c-&gt;model('Schema::Foo');
52d980cb 933 my $author_model = $model-&gt;resultset('Authors');
934
935}
936
9371;</pre>
938 </div>
939
940</div>
941</body>
942</html>