images and some more deets
[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">
451b57c2 345<pre>package Foo::Schema::Result::Author;
492be2ae 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;
451b57c2 361 'Foo::Schema::Result::Book', 'author_id'
492be2ae 362);
3631;
364</pre>
365 </div>
366
367 <div class="slide">
451b57c2 368<pre>package Foo::Schema::Result::Book;
492be2ae 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;
451b57c2 389 'Foo::Schema::Result::Author', 'author_id'
492be2ae 390);
3911;
392</pre>
52d980cb 393 </div>
394
395 <div class="slide">
9158dee5 396 <h1>-&gt;deploy</h1>
397 <p>Perl -&gt; DB</p>
398<pre>my $schema = Foo::Schema-&gt;connect($dsn, $user, $pass);
399$schema-&gt;deploy
400</pre>
401<p>See also: <a href="http://search.cpan.org/perldoc?DBIx::Class::DeploymentHandler">DBIx::Class::DeploymentHandler</a></p>
402 </div>
403
404 <div class="slide">
52d980cb 405 <h1>Schema::Loader</h1>
9158dee5 406 <p>DB -&gt; Perl</p>
451b57c2 407<pre>package Foo::Schema;
c7321880 408use strict; use warnings;
409use base 'DBIx::Class::Schema::Loader';
410__PACKAGE__-&gt;loader_options({
411 naming =&gt; 'v7',
412 debug =&gt; $ENV{DBIC_TRACE},
413});
4141;
415
416# elsewhere...
417
451b57c2 418my $schema = Foo::Schema-&gt;connect($dsn, $user, $pass);
c7321880 419</pre>
52d980cb 420 </div>
421
422 <div class="slide">
6e5edefe 423 <h1>Splitting Logic Cleanly</h1>
451b57c2 424 <p>Foo::Schema::Result::Bar = individual row</p>
425 <p>Foo::Schema::ResultSet::Bar = searches / table </p>
52d980cb 426 </div>
427
428 <div class="slide">
6e5edefe 429 <h1>Using your Schema</h1>
430<pre>#!perl
431use strict; use warnings;
432use lib 'lib';
451b57c2 433use Foo::Schema;
434my $schema = Foo::Schema-&gt;connect($dns, $user, $pass);
6e5edefe 435my $author_rs = $schema-&gt;resultset('Author');
436my $author = $author_rs-&gt;create({
437 name =&gt; 'Douglas Adams',
438});
439my $book = $author-&gt;add_to_books({
440 title =&gt; '42',
441});
442</pre>
52d980cb 443 </div>
444
445 <div class="slide">
446 <h1>DEBUGGING</h1>
447 <pre>DBIC_TRACE=1 ./your_script.pl</pre>
448 </div>
449
450 <div class="slide">
52d980cb 451 <h1>SQL - debugging</h1>
452<pre>INSERT INTO authors (name)
453 VALUES (?): 'Douglas Adams'
454
455INSERT INTO books (author, title)
456 VALUES (?, ?): '5', '42'</pre>
457 </div>
458
459 <div class="slide">
460 <h1>overloading</h1>
451b57c2 461<pre>Foo::Schema::Result::Book
462Foo::Schema::ResultSet::Book
463Foo::Schema::Result::Author
464Foo::Schema::ResultSet::Book</pre>
52d980cb 465 </div>
466
467 <div class="slide">
468 <h1>Result::</h1>
2a65778d 469<pre>package Foo::Schema::Result::Book;
470use base 'DBIx::Class::Core';
52d980cb 471use strict;
472use warnings;
473
6e5edefe 474# Result code here
475
52d980cb 476sub isbn {
477 my $self = shift;
478
479 # search amazon or something
480 my $api = Amazon::API-&gt;book({
481 title =&gt; $self-&gt;title
482 });
483
484 return $api-&gt;isbn;
485}
486
4871;</pre>
488 </div>
489
490 <div class="slide">
491 <h1>Result::</h1>
492<pre>print $book-&gt;isbn;</pre>
493 </div>
494
495 <div class="slide">
496 <h1>Result:: (inflating)</h1>
2a65778d 497<pre>package Foo::Schema::Result::Book;
498use base 'DBIx::Class::Core';
52d980cb 499use strict;
500use warnings;
501
451b57c2 502# Result code here
503
504__PACKAGE__-&gt;load_components('InflateColumn');
52d980cb 505use DateTime::Format::MySQL;
506
507__PACKAGE__-&gt;<strong>inflate_column</strong>(
508 <strong>date_published</strong> =&gt; {
509 inflate =&gt; sub { DateTime::Format::MySQL-&gt;parse_date(shift) },
510 deflate =&gt; sub { shift-&gt;ymd},
451b57c2 511 },
52d980cb 512);
513# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
514 </div>
515
516 <div class="slide">
52d980cb 517 <h1>Result:: (deflating)</h1>
518<pre>$book-&gt;date_published(DateTime-&gt;now);
519$book-&gt;update;</pre>
520 </div>
521
522 <div class="slide">
523 <h1>Result:: (inflating)</h1>
524<pre>my $date_published = $book-&gt;date_published;
525print $date_published-&gt;month_abbr;</pre>
526
527<strong><em>Nov</em></strong>
528 </div>
529
530 <div class="slide">
531 <h1>ResultSets::</h1>
41a0eb8e 532<pre>package Foo::Schema::ResultSet::Books;
52d980cb 533use base 'DBIx::Class::ResultSet';
534sub the_ultimate_books {
535 my $self = shift;
536 return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } });
537}
538sub by_author {
539 my ( $self, $author ) = @_;
540 return $self-&gt;search({ author =&gt; $author-&gt;id })
541}
542
5431;</pre>
544 </div>
545
546 <div class="slide">
547 <h1>ResultSets::</h1>
41a0eb8e 548<pre>use Foo::Schema;
451b57c2 549my $schema = Foo::Schema-&gt;connect(...);
550my $book_rs = Foo::Schema-&gt;resultset('Book');
551my $book_search = $book_rs-&gt;the_ultimate_books;
552my @books = $book_search-&gt;all;</pre>
52d980cb 553 </div>
554
555 <div class="slide">
451b57c2 556 <h1>ResultSets: Chaining</h1>
557<pre>
558my $book_rs = $schema-&gt;resultset('Book');
559my $author_rs = $schema-&gt;resultset('Author');
52d980cb 560my $author = $author_model-&gt;search({ name =&gt; 'Douglas Adams' })-&gt;single;
561my $book_rs = $book_model-&gt;the_ultimate_books-&gt;by_author($author);
562my @books = $book_rs-&gt;all;</pre>
563 </div>
564
565 <div class="slide">
451b57c2 566 <h1>ResultSets: Chaining</h1>
567<pre>$book_rs = $schema-&gt;resultset('Book')
52d980cb 568 -&gt;the_ultimate_books
569 -&gt;by_author($author);</pre>
570or
571
451b57c2 572<pre>my $book_rs = $schema-&gt;resultset('Book')
2a65778d 573 -&gt;the_ultimate_books;
52d980cb 574$book_rs = $book_rs-&gt;by_author($author);</pre>
575<pre># Debug (SQL):
576
577# SELECT me.id, me.title, me.date_published, me.author
578# FROM books me
579# WHERE ( ( ( author = ? ) AND ( title LIKE ? ) ) ): '5', '%42%'
580# WHERE ( ( ( author = ? ) AND ( title LIKE ? ) ) ): '5', '%42%'</pre>
581 </div>
582
583 <div class="slide">
584 <h1>ResultSets::chaining</h1>
585<pre>my $rs = $book_model
586 -&gt;category('childrens')
587 -&gt;by_author($author)
588 -&gt;published_after('1812')
589 -&gt;first_page_contains('once upon')
590 -&gt;rating_greater_than(4);
591
592my @books = $rs-&gt;all;</pre>
593 </div>
594
595 <div class="slide">
596 <h1>overloading before new record</h1>
2a65778d 597 <pre>package Foo::Schema::Result::Author;
598use base 'DBIx::Class::Core';
52d980cb 599
600sub new {
601 my ( $class, $attrs ) = @_;
602 # Mess with $attrs
603 my $new = $class-&gt;next::method($attrs);
604 return $new
605}
606
6071;</pre>
608
609 <div class="slide">
6548782a 610 <h1>Relationships</h1>
52d980cb 611 </div>
612
613 <div class="slide">
6548782a 614 <h1>Multiple Authors</h1>
52d980cb 615 </div>
616
617 <div class="slide">
618 <h1>a few relationships</h1>
9158dee5 619 <img src="img/afewrels.png" />
52d980cb 620 </div>
621
622 <div class="slide">
6548782a 623 <h1>Join Table</h1>
52d980cb 624<pre>CREATE TABLE author_and_books(
6548782a 625 book_id int(8),
626 author_id int(8),
627 foreign key (book_id) references books(id),
628 foreign key (author_id) references authors(id)
52d980cb 629) engine = InnoDB DEFAULT CHARSET=utf8;
630
6548782a 631ALTER TABLE `books` DROP `author`;</pre>
52d980cb 632 </div>
633
634 <div class="slide">
635 <h1>has_many</h1>
9158dee5 636 <img src="img/hasmany1.png" />
52d980cb 637 </div>
638
639 <div class="slide">
640 <h1>has_many</h1>
6548782a 641<pre>package Foo::Schema::<strong>Result::Book</strong>;
52d980cb 642
6548782a 643__PACKAGE__-&gt;has_many( author_and_books =&gt;
644 'Foo::Schema::Result::Author_Book', 'book_id'
52d980cb 645);
52d980cb 646 </div>
647
648 <div class="slide">
649 <h1>belongs_to</h1>
9158dee5 650 <img src="img/belongsto1.png" />
52d980cb 651 </div>
652
653 <div class="slide">
654 <h1>belongs_to</h1>
6548782a 655<pre>package Foo::Schema::<strong>Result::Author_Book</strong>;
52d980cb 656
657__PACKAGE__-&gt;belongs_to(
6548782a 658 book =&gt;
659 'Foo::Schema::Result::Book', 'book_id'
52d980cb 660);
661</pre>
662 </div>
663
664 <div class="slide">
665 <h1>same for Authors</h1>
9158dee5 666 <img src="img/authors.png" />
52d980cb 667 </div>
668
669 <div class="slide">
52d980cb 670 <h1>many_to_many</h1>
9158dee5 671 <img src="img/m2m.png" />
52d980cb 672 </div>
673
674 <div class="slide">
675 <h1>many_to_many</h1>
2a65778d 676 <pre>package Foo::Schema::<strong>Result::Book</strong>;
677use base 'DBIx::Class::Core';
52d980cb 678
679__PACKAGE__-&gt;many_to_many(
6548782a 680 authors =&gt; 'author_and_books', 'author'
52d980cb 681);
682
6831;
6548782a 684</pre>
52d980cb 685 </div>
686
687 <div class="slide">
688 <h1>many_to_many</h1>
2a65778d 689 <pre>package Foo::Schema::<strong>Result::Book</strong>;
690use base 'DBIx::Class::Core';
52d980cb 691
692__PACKAGE__-&gt;many_to_many(
693 authors <strong># Accessor name</strong>
694 =&gt; "author_and_books", <strong># has_many</strong>
695 'author' <strong># foreign relationship name</strong>
696);
697
6981;</pre>
699 </div>
700
701 <div class="slide">
702 <h1>many_to_many</h1>
2a65778d 703 <pre>package Foo::Schema::Result::Author;
704use base 'DBIx::Class::Core';
52d980cb 705
706__PACKAGE__-&gt;many_to_many(
707 "books" <strong># Accessor Name</strong>
708 =&gt; "author_and_books", <strong># has_many accessor_name</strong>
709 'book' <strong># foreign relationship name</strong>
710);
711
7121;
6548782a 713</pre>
52d980cb 714 </div>
715
716 <div class="slide">
6c562ff1 717 <h1>Using many_to_many</h1>
718 <pre>#!perl
41a0eb8e 719use Foo::Schema;
6c562ff1 720my $schema = Foo::Schema-&gt;connect(...);
721my $author_rs = $schema-&gt;resultset('Authors');
722my $author = $author_model-&gt;search({
52d980cb 723 name =&gt; 'Douglas Adams',
724})-&gt;single;
725$author-&gt;add_to_books({
726 title =&gt; 'A new book',
727});</pre>
728 </div>
729
730 <div class="slide">
731 <h1>using many_to_many</h1>
732 <pre>my $author = $author_model-&gt;search({
733 name =&gt; 'Douglas Adams',
734})-&gt;single;
735<strong>$author-&gt;add_to_books({
736 title =&gt; 'A new book',
737});</strong>
738
739# SELECT me.id, me.name FROM authors me
740# WHERE ( name = ? ): 'Douglas Adams';
741# INSERT INTO books (title) VALUES (?): 'A new book';
742# INSERT INTO author_and_books (author, book)
743# VALUES (?, ?): '5', '2';</pre>
744 </div>
745
746 <div class="slide">
747 <h1>using many_to_many</h1>
748 <pre>$author-&gt;add_to_books($book);
749
750$book-&gt;add_to_authors($author_1);
751$book-&gt;add_to_authors($author_2);</pre>
752 </div>
753
754 <div class="slide">
52d980cb 755 <h1>errors</h1>
756 <p>Read them closely!</p>
757 </div>
758
759 <div class="slide">
760 <h1>error messages</h1>
41a0eb8e 761 <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 762 </div>
763
764 <div class="slide">
765 <h1>error messages</h1>
41a0eb8e 766 <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 767 </div>
768
769 <div class="slide">
770 <h1>errors</h1>
771 <ul>
772 <li>Turn on debugging</li>
773 <li>Read error messages (sometimes useful!)</li>
774 <li>Check field names</li>
775 <li>Check package names</li>
776 <li>Check which database you are connected to (dev/test/live?) - repeat above</li>
777 </ul>
778 </div>
779
780 <div class="slide">
9158dee5 781 <h1>LOTS more Features</h1>
782 <ul>
783 <li>FilterColumn</li>
784 <li>Transactions</li>
785 <li>HashRefInflator</li>
786 <li>Subqueries</li>
787 <li>ResultSetColumn</li>
788 </ul>
789 </div>
790
791 <div class="slide">
52d980cb 792 <h1>bonus slides!</h1>
793 </div>
794
795 <div class="slide">
796 <h1>Template Toolkit</h1>
797 <ul>
798 <li><pre>[% author.books.count %]</pre> not working?</li>
799 <li>TT all methods are called in list context</li>
800 <li><pre>[% author.books<strong>_rs</strong>.count %]</pre> scalar context</li>
801 <li><em>Available for all relationships</em></li>
802 </ul>
803 </div>
804
805 <div class="slide">
806 <h1>Catalyst</h1>
0cffcad7 807 <pre>package Your::App::Model::<strong>Foo</strong>;
41a0eb8e 808use base qw(<strong>Catalyst::Model::Schema::Schema</strong>);
52d980cb 809
810use strict;
811use warnings;
812
813__PACKAGE__-&gt;config(
41a0eb8e 814 schema_class =&gt; '<strong>Foo::Schema</strong>',
52d980cb 815);
816
8171;</pre>
818 <p>Keep your Schema in a <em>separate</em> package to your Catalyst application</p>
819 </div>
820
821 <div class="slide">
822 <h1>Catalyst</h1>
823<pre>sub action_name : Local {
824 my ($self, $c) = @_;
825
41a0eb8e 826 my $model = $c-&gt;model('Schema::Foo');
52d980cb 827 my $author_model = $model-&gt;resultset('Authors');
828
829}
830
8311;</pre>
832 </div>
833
834</div>
835</body>
836</html>