lots of little tweaks
[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">
52d980cb 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">
5cac74c7 191 <h1>SQL: Create</h1>
52d980cb 192<pre>my $sth = $dbh-&gt;prepare('
193 INSERT INTO books
01b7b88c 194 (title, author_id)
52d980cb 195 values (?,?)
196');
197
198$sth-&gt;execute(
199 'A book title', $author_id
200);</pre>
201 </div>
202
203 <div class="slide">
5cac74c7 204 <h1>SQL: Read</h1>
52d980cb 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">
5cac74c7 214 <h1>SQL: Read</h1>
52d980cb 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">
5cac74c7 225 <h1>SQL: Update</h1>
52d980cb 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">
5cac74c7 238 <h1>SQL: Delete</h1>
52d980cb 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">
5cac74c7 252 <h1>DBIC: Create</h1>
01b7b88c 253<pre>my $book = $book_rs-&gt;create({
254 title =&gt; 'A book title',
255 author_id =&gt; $author_id,
52d980cb 256});</pre>
257 <p>Look ma, no SQL!</p>
52d980cb 258 </div>
259
260 <div class="slide">
5cac74c7 261 <h1>DBIC: Create</h1>
01b7b88c 262<pre>my $pratchett = $author_rs-&gt;create({
52d980cb 263 name =&gt; 'Terry Pratchett',
264});</pre>
265 </div>
266
267 <div class="slide">
5cac74c7 268 <h1>DBIC: Create</h1>
52d980cb 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">
5cac74c7 280 <h1>DBIC: Read</h1>
01b7b88c 281 <p>DBIx::Class - TIMTOWTDI</p>
52d980cb 282 </div>
283
284 <div class="slide">
5cac74c7 285 <h1>DBIC: Read</h1>
01b7b88c 286<pre>my $book = $book_rs-&gt;find($book_id);
52d980cb 287
01b7b88c 288my $book = $book_rs-&gt;search({
52d980cb 289 title =&gt; 'A book title',
5cac74c7 290}, { rows =&gt; 1 })-&gt;single;
52d980cb 291
01b7b88c 292my @books = $book_rs-&gt;search({
52d980cb 293 author =&gt; $author_id,
294})-&gt;all;</pre>
295 </div>
296
297 <div class="slide">
5cac74c7 298 <h1>DBIC: Read</h1>
299<pre>while( my $book = $books_rs-&gt;next ) {
52d980cb 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">
5cac74c7 309 <h1>DBIC: Read</h1>
01b7b88c 310<pre>my $resultset = $book_rs-&gt;search({
52d980cb 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">
5cac74c7 318 <h1>DBIC: Update</h1>
52d980cb 319<pre>$book-&gt;update({
320 title =&gt; 'New title',
321});</pre>
322 </div>
323
324 <div class="slide">
5cac74c7 325 <h1>DBIC: Delete</h1>
52d980cb 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">
451b57c2 334<pre>package Foo::Schema::Result::Author;
492be2ae 335__PACKAGE__-&gt;table('authors');
336__PACKAGE__-&gt;add_columns(
337 id =&gt; {
01b7b88c 338 data_type =&gt; 'int',
339 is_auto_increment =&gt; 1
492be2ae 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;
451b57c2 349 'Foo::Schema::Result::Book', 'author_id'
492be2ae 350);
3511;
352</pre>
353 </div>
354
355 <div class="slide">
01b7b88c 356<pre style="float: left; font-size: 80%;">package Foo::Schema::Result::Book;
492be2ae 357use strict; use warnings;
358__PACKAGE__-&gt;table('books');
359__PACKAGE__-&gt;add_columns(
360 id =&gt; {
01b7b88c 361 data_type =&gt; 'int',
362 is_auto_increment =&gt; 1
492be2ae 363 },
364 name =&gt; {
365 data_type =&gt; 'varchar',
366 is_nullable =&gt; 1,
367 size =&gt; 255,
368 },
01b7b88c 369</pre>
370<pre style="float: left; font-size: 80%;">
492be2ae 371 author_id =&gt; {
372 data_type =&gt; 'int',
373 size =&gt; 8,
492be2ae 374 },
375);
376__PACKAGE__-&gt;set_primary_key('id');
377__PACKAGE__-&gt;belongs_to( author =&gt;
451b57c2 378 'Foo::Schema::Result::Author', 'author_id'
492be2ae 379);
3801;
381</pre>
52d980cb 382 </div>
383
384 <div class="slide">
9158dee5 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">
52d980cb 394 <h1>Schema::Loader</h1>
9158dee5 395 <p>DB -&gt; Perl</p>
451b57c2 396<pre>package Foo::Schema;
c7321880 397use strict; use warnings;
398use base 'DBIx::Class::Schema::Loader';
399__PACKAGE__-&gt;loader_options({
400 naming =&gt; 'v7',
401 debug =&gt; $ENV{DBIC_TRACE},
402});
4031;
404
405# elsewhere...
406
451b57c2 407my $schema = Foo::Schema-&gt;connect($dsn, $user, $pass);
c7321880 408</pre>
52d980cb 409 </div>
410
411 <div class="slide">
6e5edefe 412 <h1>Splitting Logic Cleanly</h1>
451b57c2 413 <p>Foo::Schema::Result::Bar = individual row</p>
414 <p>Foo::Schema::ResultSet::Bar = searches / table </p>
52d980cb 415 </div>
416
417 <div class="slide">
6e5edefe 418 <h1>Using your Schema</h1>
419<pre>#!perl
420use strict; use warnings;
421use lib 'lib';
451b57c2 422use Foo::Schema;
423my $schema = Foo::Schema-&gt;connect($dns, $user, $pass);
6e5edefe 424my $author_rs = $schema-&gt;resultset('Author');
425my $author = $author_rs-&gt;create({
426 name =&gt; 'Douglas Adams',
427});
428my $book = $author-&gt;add_to_books({
429 title =&gt; '42',
430});
431</pre>
52d980cb 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">
52d980cb 440 <h1>SQL - debugging</h1>
441<pre>INSERT INTO authors (name)
442 VALUES (?): 'Douglas Adams'
443
444INSERT INTO books (author, title)
445 VALUES (?, ?): '5', '42'</pre>
446 </div>
447
448 <div class="slide">
449 <h1>overloading</h1>
451b57c2 450<pre>Foo::Schema::Result::Book
451Foo::Schema::ResultSet::Book
452Foo::Schema::Result::Author
453Foo::Schema::ResultSet::Book</pre>
52d980cb 454 </div>
455
456 <div class="slide">
457 <h1>Result::</h1>
2a65778d 458<pre>package Foo::Schema::Result::Book;
459use base 'DBIx::Class::Core';
52d980cb 460use strict;
461use warnings;
462
6e5edefe 463# Result code here
464
52d980cb 465sub 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
4761;</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>
2a65778d 486<pre>package Foo::Schema::Result::Book;
487use base 'DBIx::Class::Core';
52d980cb 488use strict;
489use warnings;
490
451b57c2 491# Result code here
492
493__PACKAGE__-&gt;load_components('InflateColumn');
52d980cb 494use 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},
451b57c2 500 },
52d980cb 501);
502# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
503 </div>
504
505 <div class="slide">
52d980cb 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;
514print $date_published-&gt;month_abbr;</pre>
515
516<strong><em>Nov</em></strong>
517 </div>
518
519 <div class="slide">
520 <h1>ResultSets::</h1>
41a0eb8e 521<pre>package Foo::Schema::ResultSet::Books;
52d980cb 522use base 'DBIx::Class::ResultSet';
523sub the_ultimate_books {
524 my $self = shift;
525 return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } });
526}
527sub by_author {
528 my ( $self, $author ) = @_;
529 return $self-&gt;search({ author =&gt; $author-&gt;id })
530}
531
5321;</pre>
533 </div>
534
535 <div class="slide">
536 <h1>ResultSets::</h1>
41a0eb8e 537<pre>use Foo::Schema;
451b57c2 538my $schema = Foo::Schema-&gt;connect(...);
539my $book_rs = Foo::Schema-&gt;resultset('Book');
540my $book_search = $book_rs-&gt;the_ultimate_books;
541my @books = $book_search-&gt;all;</pre>
52d980cb 542 </div>
543
544 <div class="slide">
451b57c2 545 <h1>ResultSets: Chaining</h1>
546<pre>
01b7b88c 547my $book_rs = $schema-&gt;resultset('Book');
548my $author_rs = $schema-&gt;resultset('Author');
549my $author = $author_rs-&gt;search({ name =&gt; 'Douglas Adams' })-&gt;single;
550$book_rs = $book_rs-&gt;the_ultimate_books-&gt;by_author($author);
551my @books = $book_rs-&gt;all;</pre>
52d980cb 552 </div>
553
554 <div class="slide">
451b57c2 555 <h1>ResultSets: Chaining</h1>
556<pre>$book_rs = $schema-&gt;resultset('Book')
52d980cb 557 -&gt;the_ultimate_books
558 -&gt;by_author($author);</pre>
559or
560
451b57c2 561<pre>my $book_rs = $schema-&gt;resultset('Book')
2a65778d 562 -&gt;the_ultimate_books;
52d980cb 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">
01b7b88c 573 <h1>ResultSets: Chaining</h1>
574<pre>my $rs = $book_rs
52d980cb 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
581my @books = $rs-&gt;all;</pre>
582 </div>
583
584 <div class="slide">
585 <h1>overloading before new record</h1>
2a65778d 586 <pre>package Foo::Schema::Result::Author;
587use base 'DBIx::Class::Core';
52d980cb 588
589sub new {
590 my ( $class, $attrs ) = @_;
591 # Mess with $attrs
592 my $new = $class-&gt;next::method($attrs);
593 return $new
594}
595
5961;</pre>
597
598 <div class="slide">
6548782a 599 <h1>Relationships</h1>
52d980cb 600 </div>
601
602 <div class="slide">
6548782a 603 <h1>Multiple Authors</h1>
01b7b88c 604 <p>We want to allow a book to be by more than one author</p>
52d980cb 605 </div>
606
607 <div class="slide">
608 <h1>a few relationships</h1>
9158dee5 609 <img src="img/afewrels.png" />
52d980cb 610 </div>
611
612 <div class="slide">
6548782a 613 <h1>Join Table</h1>
52d980cb 614<pre>CREATE TABLE author_and_books(
6548782a 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)
52d980cb 619) engine = InnoDB DEFAULT CHARSET=utf8;
620
01b7b88c 621ALTER TABLE `books` DROP `author_id`;</pre>
52d980cb 622 </div>
623
624 <div class="slide">
625 <h1>has_many</h1>
9158dee5 626 <img src="img/hasmany1.png" />
52d980cb 627 </div>
628
629 <div class="slide">
630 <h1>has_many</h1>
6548782a 631<pre>package Foo::Schema::<strong>Result::Book</strong>;
52d980cb 632
6548782a 633__PACKAGE__-&gt;has_many( author_and_books =&gt;
634 'Foo::Schema::Result::Author_Book', 'book_id'
52d980cb 635);
52d980cb 636 </div>
637
638 <div class="slide">
639 <h1>belongs_to</h1>
9158dee5 640 <img src="img/belongsto1.png" />
52d980cb 641 </div>
642
643 <div class="slide">
644 <h1>belongs_to</h1>
6548782a 645<pre>package Foo::Schema::<strong>Result::Author_Book</strong>;
52d980cb 646
647__PACKAGE__-&gt;belongs_to(
6548782a 648 book =&gt;
649 'Foo::Schema::Result::Book', 'book_id'
52d980cb 650);
651</pre>
652 </div>
653
654 <div class="slide">
655 <h1>same for Authors</h1>
9158dee5 656 <img src="img/authors.png" />
52d980cb 657 </div>
658
659 <div class="slide">
52d980cb 660 <h1>many_to_many</h1>
9158dee5 661 <img src="img/m2m.png" />
52d980cb 662 </div>
663
664 <div class="slide">
665 <h1>many_to_many</h1>
2a65778d 666 <pre>package Foo::Schema::<strong>Result::Book</strong>;
667use base 'DBIx::Class::Core';
52d980cb 668
669__PACKAGE__-&gt;many_to_many(
6548782a 670 authors =&gt; 'author_and_books', 'author'
52d980cb 671);
672
6731;
6548782a 674</pre>
52d980cb 675 </div>
676
677 <div class="slide">
678 <h1>many_to_many</h1>
2a65778d 679 <pre>package Foo::Schema::<strong>Result::Book</strong>;
680use base 'DBIx::Class::Core';
52d980cb 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
6881;</pre>
689 </div>
690
691 <div class="slide">
692 <h1>many_to_many</h1>
2a65778d 693 <pre>package Foo::Schema::Result::Author;
694use base 'DBIx::Class::Core';
52d980cb 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
7021;
6548782a 703</pre>
52d980cb 704 </div>
705
706 <div class="slide">
6c562ff1 707 <h1>Using many_to_many</h1>
708 <pre>#!perl
41a0eb8e 709use Foo::Schema;
6c562ff1 710my $schema = Foo::Schema-&gt;connect(...);
711my $author_rs = $schema-&gt;resultset('Authors');
01b7b88c 712my $author = $author_rs-&gt;search({
52d980cb 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>
01b7b88c 722 <pre>my $author = $author_rs-&gt;search({
52d980cb 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">
52d980cb 745 <h1>errors</h1>
746 <p>Read them closely!</p>
747 </div>
748
749 <div class="slide">
750 <h1>error messages</h1>
01b7b88c 751<pre>DBIx::Class::Schema::Loader::connection(): Failed to load external
752class definition for 'Foo::Schema::Result::Authors': Can't locate object
753method "many_to_many" via package "Foo::Schema::Result::Author" at
754lib/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>
52d980cb 756 </div>
757
758 <div class="slide">
759 <h1>error messages</h1>
01b7b88c 760<pre>DBIx::Class::Schema::Loader::connection(): Failed to load external
761class definition for 'Foo::Schema::Result::Authors': Can't locate object
762method "many_to_many" via package "Foo::Schema::<strong>Result::Author</strong>" at
763lib/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>
52d980cb 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">
9158dee5 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>
01b7b88c 786 <li>Aggregate Queries</li>
9158dee5 787 </ul>
788 </div>
789
790 <div class="slide">
52d980cb 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>
0cffcad7 806 <pre>package Your::App::Model::<strong>Foo</strong>;
41a0eb8e 807use base qw(<strong>Catalyst::Model::Schema::Schema</strong>);
52d980cb 808
809use strict;
810use warnings;
811
812__PACKAGE__-&gt;config(
41a0eb8e 813 schema_class =&gt; '<strong>Foo::Schema</strong>',
52d980cb 814);
815
8161;</pre>
01b7b88c 817 <p>Keep your Schema in a <em>separate</em> package from your Catalyst application</p>
52d980cb 818 </div>
819
820 <div class="slide">
821 <h1>Catalyst</h1>
822<pre>sub action_name : Local {
823 my ($self, $c) = @_;
824
01b7b88c 825 my $schema = $c-&gt;model('Schema::Foo');
826 my $author_rs = $schema-&gt;resultset('Authors');
52d980cb 827
828}
829
8301;</pre>
831 </div>
832
833</div>
834</body>
835</html>