lots of little tweaks
[dbsrgits/dbix-class-introduction-presentation.git] / slideshow.html
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>
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>
80       <h4>Justin D. Hunter</h4>
81       <h4>Arthur Axel "fREW" Schmidt</h4>
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>
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>
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">
118       <h1>point of note</h1>
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>
123
124       <p>This talk is about making it easy so we are less likely to get
125       confused</p>
126    </div>
127
128    <div class="slide">
129       <h1>Examples Table Setup</h1>
130       <ul>
131          <li>Authors</li>
132          <li>Books</li>
133       </ul>
134       <em>MySQL not recommended</em>
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>
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(
162    id        int(8) primary key auto_increment,
163    title     varchar(255),
164    author_id int(8),foreign key (author)
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>
173       <p>Ensure foreign key is the same type and size in both tables</p>
174    </div>
175
176    <div class="slide">
177       <h1>CRUD compared</h1>
178       <ul>
179          <li><strong>C</strong> - Create</li>
180          <li><strong>R</strong> - Read</li>
181          <li><strong>U</strong> - Update</li>
182          <li><strong>D</strong> - Delete</li>
183       </ul>
184    </div>
185
186    <div class="slide">
187       <h1>Manual (SQL)</h1>
188    </div>
189
190    <div class="slide">
191       <h1>SQL: Create</h1>
192 <pre>my $sth = $dbh-&gt;prepare('
193    INSERT INTO books
194    (title, author_id)
195    values (?,?)
196 ');
197
198 $sth-&gt;execute(
199   'A book title', $author_id
200 );</pre>
201    </div>
202
203    <div class="slide">
204       <h1>SQL: Read</h1>
205 <pre>my $sth = $dbh-&gt;prepare('
206    SELECT title,
207    authors.name as author_name
208    FROM books, authors
209    WHERE books.author = authors.id
210 ');</pre>
211    </div>
212
213    <div class="slide">
214       <h1>SQL: Read</h1>
215 <pre>while( my $book = $sth-&gt;fetchrow_hashref() ) {
216   print 'Author of '
217      . $book-&gt;{title}
218      . ' is '
219      . $book-&gt;{author_name}
220      . "\n";
221 }</pre>
222    </div>
223
224    <div class="slide">
225       <h1>SQL: Update</h1>
226 <pre>my $update = $dbh-&gt;prepare('
227    UPDATE books
228    SET title = ?
229    WHERE id = ?
230 ');
231
232 $update-&gt;execute(
233   'New title',<strong>$book_id</strong>
234 );</pre>
235    </div>
236
237    <div class="slide">
238       <h1>SQL: Delete</h1>
239 <pre>my $delete = $dbh-&gt;prepare('
240    DELETE FROM books
241    WHERE id = ?
242 ');
243
244 $delete-&gt;execute(<strong>$book_id</strong>);</pre>
245    </div>
246
247    <div class="slide">
248       <h1>DBIx::Class</h1>
249    </div>
250
251    <div class="slide">
252       <h1>DBIC: Create</h1>
253 <pre>my $book = $book_rs-&gt;create({
254    title     =&gt; 'A book title',
255    author_id =&gt; $author_id,
256 });</pre>
257       <p>Look ma, no SQL!</p>
258    </div>
259
260    <div class="slide">
261       <h1>DBIC: Create</h1>
262 <pre>my $pratchett = $author_rs-&gt;create({
263    name =&gt; 'Terry Pratchett',
264 });</pre>
265    </div>
266
267    <div class="slide">
268       <h1>DBIC: Create</h1>
269 <pre>my $book = $pratchett-&gt;create_related(
270   <strong>books</strong> =&gt; {
271    title =&gt; 'Another Discworld book',
272 });</pre>
273 <strong>or</strong>
274 <pre>my $book = $pratchett-&gt;add_to_<strong>books</strong>({
275    title =&gt; 'Another Discworld book',
276 });</pre>
277    </div>
278
279    <div class="slide">
280       <h1>DBIC: Read</h1>
281       <p>DBIx::Class - TIMTOWTDI</p>
282    </div>
283
284    <div class="slide">
285       <h1>DBIC: Read</h1>
286 <pre>my $book = $book_rs-&gt;find($book_id);
287
288 my $book = $book_rs-&gt;search({
289    title =&gt; 'A book title',
290 }, { rows =&gt; 1 })-&gt;single;
291
292 my @books = $book_rs-&gt;search({
293    author =&gt; $author_id,
294 })-&gt;all;</pre>
295    </div>
296
297    <div class="slide">
298       <h1>DBIC: Read</h1>
299 <pre>while( my $book = $books_rs-&gt;next ) {
300  print 'Author of '
301     . $book-&gt;title
302     . ' is '
303     . $book-&gt;author-&gt;name
304     . "\n";
305 }</pre>
306    </div>
307
308    <div class="slide">
309       <h1>DBIC: Read</h1>
310 <pre>my $resultset = $book_rs-&gt;search({
311    author =&gt; $author_id,
312 });</pre>
313       <p>Search takes SQL::Abstract formatted queries</p>
314       <pre>&gt; perldoc SQL::Abstract</p>
315    </div>
316
317    <div class="slide">
318       <h1>DBIC: Update</h1>
319 <pre>$book-&gt;update({
320   title =&gt; 'New title',
321 });</pre>
322    </div>
323
324    <div class="slide">
325       <h1>DBIC: Delete</h1>
326 <pre>$book-&gt;delete;</pre>
327    </div>
328
329    <div class="slide">
330       <h1>Creating models</h1>
331    </div>
332
333    <div class="slide">
334 <pre>package Foo::Schema::Result::Author;
335 __PACKAGE__-&gt;table('authors');
336 __PACKAGE__-&gt;add_columns(
337   id =&gt; {
338     data_type         =&gt; 'int',
339     is_auto_increment =&gt; 1
340   },
341   title =&gt; {
342     data_type   =&gt; 'varchar',
343     is_nullable =&gt; 1,
344     size        =&gt; 255,
345   },
346 );
347 __PACKAGE__-&gt;set_primary_key('id');
348 __PACKAGE__-&gt;has_many( books =&gt;
349    'Foo::Schema::Result::Book', 'author_id'
350 );
351 1;
352 </pre>
353    </div>
354
355    <div class="slide">
356 <pre style="float: left; font-size: 80%;">package Foo::Schema::Result::Book;
357 use strict; use warnings;
358 __PACKAGE__-&gt;table('books');
359 __PACKAGE__-&gt;add_columns(
360   id =&gt; {
361     data_type         =&gt; 'int',
362     is_auto_increment =&gt; 1
363   },
364   name =&gt; {
365     data_type   =&gt; 'varchar',
366     is_nullable =&gt; 1,
367     size        =&gt; 255,
368   },
369 </pre>
370 <pre style="float: left; font-size: 80%;">
371   author_id =&gt; {
372     data_type   =&gt; 'int',
373     size        =&gt; 8,
374   },
375 );
376 __PACKAGE__-&gt;set_primary_key('id');
377 __PACKAGE__-&gt;belongs_to( author =&gt;
378    'Foo::Schema::Result::Author', 'author_id'
379 );
380 1;
381 </pre>
382    </div>
383
384    <div class="slide">
385       <h1>-&gt;deploy</h1>
386       <p>Perl -&gt; DB</p>
387 <pre>my $schema = Foo::Schema-&gt;connect($dsn, $user, $pass);
388 $schema-&gt;deploy
389 </pre>
390 <p>See also: <a href="http://search.cpan.org/perldoc?DBIx::Class::DeploymentHandler">DBIx::Class::DeploymentHandler</a></p>
391    </div>
392
393    <div class="slide">
394       <h1>Schema::Loader</h1>
395       <p>DB -&gt; Perl</p>
396 <pre>package Foo::Schema;
397 use strict; use warnings;
398 use base 'DBIx::Class::Schema::Loader';
399 __PACKAGE__-&gt;loader_options({
400    naming =&gt; 'v7',
401    debug  =&gt; $ENV{DBIC_TRACE},
402 });
403 1;
404
405 # elsewhere...
406
407 my $schema = Foo::Schema-&gt;connect($dsn, $user, $pass);
408 </pre>
409    </div>
410
411    <div class="slide">
412       <h1>Splitting Logic Cleanly</h1>
413       <p>Foo::Schema::Result::Bar = individual row</p>
414       <p>Foo::Schema::ResultSet::Bar = searches / table </p>
415    </div>
416
417    <div class="slide">
418       <h1>Using your Schema</h1>
419 <pre>#!perl
420 use strict; use warnings;
421 use lib 'lib';
422 use Foo::Schema;
423 my $schema = Foo::Schema-&gt;connect($dns, $user, $pass);
424 my $author_rs = $schema-&gt;resultset('Author');
425 my $author    = $author_rs-&gt;create({
426    name =&gt; 'Douglas Adams',
427 });
428 my $book = $author-&gt;add_to_books({
429    title =&gt; '42',
430 });
431 </pre>
432    </div>
433
434    <div class="slide">
435       <h1>DEBUGGING</h1>
436       <pre>DBIC_TRACE=1 ./your_script.pl</pre>
437    </div>
438
439    <div class="slide">
440       <h1>SQL - debugging</h1>
441 <pre>INSERT INTO authors (name)
442    VALUES (?): 'Douglas Adams'
443
444 INSERT INTO books (author, title)
445    VALUES (?, ?): '5', '42'</pre>
446    </div>
447
448    <div class="slide">
449       <h1>overloading</h1>
450 <pre>Foo::Schema::Result::Book
451 Foo::Schema::ResultSet::Book
452 Foo::Schema::Result::Author
453 Foo::Schema::ResultSet::Book</pre>
454    </div>
455
456    <div class="slide">
457       <h1>Result::</h1>
458 <pre>package Foo::Schema::Result::Book;
459 use base 'DBIx::Class::Core';
460 use strict;
461 use warnings;
462
463 # Result code here
464
465 sub isbn {
466    my $self = shift;
467
468    # search amazon or something
469    my $api = Amazon::API-&gt;book({
470       title =&gt; $self-&gt;title
471    });
472
473    return $api-&gt;isbn;
474 }
475
476 1;</pre>
477    </div>
478
479    <div class="slide">
480       <h1>Result::</h1>
481 <pre>print $book-&gt;isbn;</pre>
482    </div>
483
484    <div class="slide">
485       <h1>Result:: (inflating)</h1>
486 <pre>package Foo::Schema::Result::Book;
487 use base 'DBIx::Class::Core';
488 use strict;
489 use warnings;
490
491 # Result code here
492
493 __PACKAGE__-&gt;load_components('InflateColumn');
494 use DateTime::Format::MySQL;
495
496 __PACKAGE__-&gt;<strong>inflate_column</strong>(
497    <strong>date_published</strong> =&gt; {
498       inflate =&gt; sub { DateTime::Format::MySQL-&gt;parse_date(shift) },
499       deflate =&gt; sub { shift-&gt;ymd},
500    },
501 );
502 # Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
503    </div>
504
505    <div class="slide">
506       <h1>Result:: (deflating)</h1>
507 <pre>$book-&gt;date_published(DateTime-&gt;now);
508 $book-&gt;update;</pre>
509    </div>
510
511    <div class="slide">
512       <h1>Result:: (inflating)</h1>
513 <pre>my $date_published = $book-&gt;date_published;
514 print $date_published-&gt;month_abbr;</pre>
515
516 <strong><em>Nov</em></strong>
517    </div>
518
519    <div class="slide">
520       <h1>ResultSets::</h1>
521 <pre>package Foo::Schema::ResultSet::Books;
522 use base 'DBIx::Class::ResultSet';
523 sub the_ultimate_books {
524    my $self = shift;
525    return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } });
526 }
527 sub by_author {
528    my ( $self, $author ) = @_;
529    return $self-&gt;search({ author =&gt; $author-&gt;id })
530 }
531
532 1;</pre>
533    </div>
534
535    <div class="slide">
536       <h1>ResultSets::</h1>
537 <pre>use Foo::Schema;
538 my $schema = Foo::Schema-&gt;connect(...);
539 my $book_rs     = Foo::Schema-&gt;resultset('Book');
540 my $book_search = $book_rs-&gt;the_ultimate_books;
541 my @books       = $book_search-&gt;all;</pre>
542    </div>
543
544    <div class="slide">
545       <h1>ResultSets: Chaining</h1>
546 <pre>
547 my $book_rs   = $schema-&gt;resultset('Book');
548 my $author_rs = $schema-&gt;resultset('Author');
549 my $author    = $author_rs-&gt;search({ name =&gt; 'Douglas Adams' })-&gt;single;
550 $book_rs      = $book_rs-&gt;the_ultimate_books-&gt;by_author($author);
551 my @books     = $book_rs-&gt;all;</pre>
552    </div>
553
554    <div class="slide">
555       <h1>ResultSets: Chaining</h1>
556 <pre>$book_rs = $schema-&gt;resultset('Book')
557   -&gt;the_ultimate_books
558   -&gt;by_author($author);</pre>
559 or
560
561 <pre>my $book_rs = $schema-&gt;resultset('Book')
562   -&gt;the_ultimate_books;
563 $book_rs = $book_rs-&gt;by_author($author);</pre>
564 <pre># Debug (SQL):
565
566 # SELECT me.id, me.title, me.date_published, me.author
567 #   FROM books me
568 #   WHERE ( ( ( author = ? ) AND ( title LIKE ? ) ) ): '5', '%42%'
569 #   WHERE ( ( ( author = ? ) AND ( title LIKE ? ) ) ): '5', '%42%'</pre>
570    </div>
571
572    <div class="slide">
573       <h1>ResultSets: Chaining</h1>
574 <pre>my $rs = $book_rs
575   -&gt;category('childrens')
576   -&gt;by_author($author)
577   -&gt;published_after('1812')
578   -&gt;first_page_contains('once upon')
579   -&gt;rating_greater_than(4);
580
581 my @books = $rs-&gt;all;</pre>
582    </div>
583
584    <div class="slide">
585       <h1>overloading before new record</h1>
586       <pre>package Foo::Schema::Result::Author;
587 use base 'DBIx::Class::Core';
588
589 sub new {
590    my ( $class, $attrs ) = @_;
591    # Mess with $attrs
592    my $new = $class-&gt;next::method($attrs);
593    return $new
594 }
595
596 1;</pre>
597
598    <div class="slide">
599       <h1>Relationships</h1>
600    </div>
601
602    <div class="slide">
603       <h1>Multiple Authors</h1>
604       <p>We want to allow a book to be by more than one author</p>
605    </div>
606
607    <div class="slide">
608       <h1>a few relationships</h1>
609       <img src="img/afewrels.png" />
610    </div>
611
612    <div class="slide">
613       <h1>Join Table</h1>
614 <pre>CREATE TABLE author_and_books(
615   book_id    int(8),
616   author_id  int(8),
617   foreign key (book_id)     references books(id),
618   foreign key (author_id)   references authors(id)
619 ) engine = InnoDB DEFAULT CHARSET=utf8;
620
621 ALTER TABLE `books` DROP `author_id`;</pre>
622    </div>
623
624    <div class="slide">
625       <h1>has_many</h1>
626       <img src="img/hasmany1.png" />
627    </div>
628
629    <div class="slide">
630       <h1>has_many</h1>
631 <pre>package Foo::Schema::<strong>Result::Book</strong>;
632
633 __PACKAGE__-&gt;has_many( author_and_books =&gt;
634    'Foo::Schema::Result::Author_Book', 'book_id'
635 );
636    </div>
637
638    <div class="slide">
639       <h1>belongs_to</h1>
640       <img src="img/belongsto1.png" />
641    </div>
642
643    <div class="slide">
644       <h1>belongs_to</h1>
645 <pre>package Foo::Schema::<strong>Result::Author_Book</strong>;
646
647 __PACKAGE__-&gt;belongs_to(
648    book =&gt;
649    'Foo::Schema::Result::Book', 'book_id'
650 );
651 </pre>
652    </div>
653
654    <div class="slide">
655       <h1>same for Authors</h1>
656       <img src="img/authors.png" />
657    </div>
658
659    <div class="slide">
660       <h1>many_to_many</h1>
661       <img src="img/m2m.png" />
662    </div>
663
664    <div class="slide">
665       <h1>many_to_many</h1>
666       <pre>package Foo::Schema::<strong>Result::Book</strong>;
667 use base 'DBIx::Class::Core';
668
669 __PACKAGE__-&gt;many_to_many(
670    authors =&gt; 'author_and_books', 'author'
671 );
672
673 1;
674 </pre>
675    </div>
676
677    <div class="slide">
678       <h1>many_to_many</h1>
679       <pre>package Foo::Schema::<strong>Result::Book</strong>;
680 use base 'DBIx::Class::Core';
681
682 __PACKAGE__-&gt;many_to_many(
683    authors <strong># Accessor name</strong>
684    =&gt; "author_and_books", <strong># has_many</strong>
685    'author' <strong># foreign relationship name</strong>
686 );
687
688 1;</pre>
689    </div>
690
691    <div class="slide">
692       <h1>many_to_many</h1>
693       <pre>package Foo::Schema::Result::Author;
694 use base 'DBIx::Class::Core';
695
696 __PACKAGE__-&gt;many_to_many(
697    "books" <strong># Accessor Name</strong>
698    =&gt; "author_and_books", <strong># has_many accessor_name</strong>
699    'book' <strong># foreign relationship name</strong>
700 );
701
702 1;
703 </pre>
704    </div>
705
706    <div class="slide">
707       <h1>Using many_to_many</h1>
708       <pre>#!perl
709 use Foo::Schema;
710 my $schema    = Foo::Schema-&gt;connect(...);
711 my $author_rs = $schema-&gt;resultset('Authors');
712 my $author    = $author_rs-&gt;search({
713    name =&gt; 'Douglas Adams',
714 })-&gt;single;
715 $author-&gt;add_to_books({
716    title =&gt; 'A new book',
717 });</pre>
718    </div>
719
720    <div class="slide">
721       <h1>using many_to_many</h1>
722       <pre>my $author = $author_rs-&gt;search({
723    name =&gt; 'Douglas Adams',
724 })-&gt;single;
725 <strong>$author-&gt;add_to_books({
726    title =&gt; 'A new book',
727 });</strong>
728
729 # SELECT me.id, me.name FROM authors me
730 #     WHERE ( name = ? ): 'Douglas Adams';
731 # INSERT INTO books (title) VALUES (?): 'A new book';
732 # INSERT INTO author_and_books (author, book)
733 #     VALUES (?, ?): '5', '2';</pre>
734    </div>
735
736    <div class="slide">
737       <h1>using many_to_many</h1>
738       <pre>$author-&gt;add_to_books($book);
739
740 $book-&gt;add_to_authors($author_1);
741 $book-&gt;add_to_authors($author_2);</pre>
742    </div>
743
744    <div class="slide">
745       <h1>errors</h1>
746       <p>Read them closely!</p>
747    </div>
748
749    <div class="slide">
750       <h1>error messages</h1>
751 <pre>DBIx::Class::Schema::Loader::connection(): Failed to load external
752 class definition for 'Foo::Schema::Result::Authors': Can't locate object
753 method "many_to_many" via package "Foo::Schema::Result::Author" at
754 lib/Foo/Schema/Result/Authors.pm line 9.Compilation failed in require at
755 /Library/Perl/5.8.8/DBIx/Class/Schema/Loader/Base.pm line 292.</pre>
756    </div>
757
758    <div class="slide">
759       <h1>error messages</h1>
760 <pre>DBIx::Class::Schema::Loader::connection(): Failed to load external
761 class definition for 'Foo::Schema::Result::Authors': Can't locate object
762 method "many_to_many" via package "Foo::Schema::<strong>Result::Author</strong>" at
763 lib/Foo/Schema/<strong>Result/Authors.pm</strong> line 9.Compilation failed in require at
764 /Library/Perl/5.8.8/DBIx/Class/Schema/Loader/Base.pm line 292.</pre>
765    </div>
766
767    <div class="slide">
768       <h1>errors</h1>
769       <ul>
770          <li>Turn on debugging</li>
771          <li>Read error messages (sometimes useful!)</li>
772          <li>Check field names</li>
773          <li>Check package names</li>
774          <li>Check which database you are connected to (dev/test/live?) - repeat above</li>
775       </ul>
776    </div>
777
778    <div class="slide">
779       <h1>LOTS more Features</h1>
780       <ul>
781          <li>FilterColumn</li>
782          <li>Transactions</li>
783          <li>HashRefInflator</li>
784          <li>Subqueries</li>
785          <li>ResultSetColumn</li>
786          <li>Aggregate Queries</li>
787       </ul>
788    </div>
789
790    <div class="slide">
791       <h1>bonus slides!</h1>
792    </div>
793
794    <div class="slide">
795       <h1>Template Toolkit</h1>
796       <ul>
797          <li><pre>[% author.books.count %]</pre> not working?</li>
798          <li>TT all methods are called in list context</li>
799          <li><pre>[% author.books<strong>_rs</strong>.count %]</pre> scalar context</li>
800          <li><em>Available for all relationships</em></li>
801       </ul>
802    </div>
803
804    <div class="slide">
805       <h1>Catalyst</h1>
806       <pre>package Your::App::Model::<strong>Foo</strong>;
807 use base qw(<strong>Catalyst::Model::Schema::Schema</strong>);
808
809 use strict;
810 use warnings;
811
812 __PACKAGE__-&gt;config(
813   schema_class =&gt; '<strong>Foo::Schema</strong>',
814 );
815
816 1;</pre>
817    <p>Keep your Schema in a <em>separate</em> package from your Catalyst application</p>
818    </div>
819
820    <div class="slide">
821       <h1>Catalyst</h1>
822 <pre>sub action_name : Local {
823   my ($self, $c) = @_;
824
825   my $schema = $c-&gt;model('Schema::Foo');
826   my $author_rs = $schema-&gt;resultset('Authors');
827
828 }
829
830 1;</pre>
831    </div>
832
833 </div>
834 </body>
835 </html>