more exmaples, less S::L
[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">
52d980cb 396 <h1>Schema::Loader</h1>
c7321880 397 <p>DB -&gt; Perl vs Perl -&gt; DB</p>
398<pre>package MyApp::Schema;
399use strict; use warnings;
400use base 'DBIx::Class::Schema::Loader';
401__PACKAGE__-&gt;loader_options({
402 naming =&gt; 'v7',
403 debug =&gt; $ENV{DBIC_TRACE},
404});
4051;
406
407# elsewhere...
408
409my $schema = MyApp::Schema-&gt;connect($dsn, $user, $pass);
410</pre>
52d980cb 411 </div>
412
413 <div class="slide">
6e5edefe 414 <h1>Splitting Logic Cleanly</h1>
415 <p>MyApp::Schema::Result::Foo = individual row</p>
416 <p>MyApp::Schema::ResultSet::Foo = searches / table </p>
52d980cb 417 </div>
418
419 <div class="slide">
6e5edefe 420 <h1>Using your Schema</h1>
421<pre>#!perl
422use strict; use warnings;
423use lib 'lib';
424use MyApp::Schema;
425my $schema = MyApp::Schema-&gt;connect($dns, $user, $pass);
426my $author_rs = $schema-&gt;resultset('Author');
427my $author = $author_rs-&gt;create({
428 name =&gt; 'Douglas Adams',
429});
430my $book = $author-&gt;add_to_books({
431 title =&gt; '42',
432});
433</pre>
52d980cb 434 </div>
435
436 <div class="slide">
437 <h1>DEBUGGING</h1>
438 <pre>DBIC_TRACE=1 ./your_script.pl</pre>
439 </div>
440
441 <div class="slide">
52d980cb 442 <h1>SQL - debugging</h1>
443<pre>INSERT INTO authors (name)
444 VALUES (?): 'Douglas Adams'
445
446INSERT INTO books (author, title)
447 VALUES (?, ?): '5', '42'</pre>
448 </div>
449
450 <div class="slide">
451 <h1>overloading</h1>
6e5edefe 452<pre>MyApp::Schema::Result::Book
453MyApp::Schema::ResultSet::Book
454MyApp::Schema::Result::Author
455MyApp::Schema::ResultSet::Book</pre>
52d980cb 456 </div>
457
458 <div class="slide">
459 <h1>Result::</h1>
41a0eb8e 460<pre>package Foo::Schema::Result::Books;
52d980cb 461use base 'DBIx::Class';
462use strict;
463use warnings;
464
6e5edefe 465# Result code here
466
52d980cb 467sub isbn {
468 my $self = shift;
469
470 # search amazon or something
471 my $api = Amazon::API-&gt;book({
472 title =&gt; $self-&gt;title
473 });
474
475 return $api-&gt;isbn;
476}
477
4781;</pre>
479 </div>
480
481 <div class="slide">
482 <h1>Result::</h1>
483<pre>print $book-&gt;isbn;</pre>
484 </div>
485
486 <div class="slide">
487 <h1>Result:: (inflating)</h1>
41a0eb8e 488<pre>package Foo::Schema::Result::Books;
52d980cb 489use base 'DBIx::Class';
490use strict;
491use warnings;
492
493use DateTime::Format::MySQL;
494
495__PACKAGE__-&gt;<strong>inflate_column</strong>(
496 <strong>date_published</strong> =&gt; {
497 inflate =&gt; sub { DateTime::Format::MySQL-&gt;parse_date(shift) },
498 deflate =&gt; sub { shift-&gt;ymd},
499 }
500);
501# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
502 </div>
503
504 <div class="slide">
505 <h1>Result:: (inflating)</h1>
41a0eb8e 506<pre>package Foo::Schema::Result::Books;
52d980cb 507use base 'DBIx::Class';
508use strict;
509use warnings;
510
511use DateTime::Format::MySQL;
512
513__PACKAGE__-&gt;inflate_column(
514 date_published =&gt; {
515 <strong>inflate =&gt; sub { DateTime::Format::MySQL-&gt;parse_date(shift) },
516 deflate =&gt; sub { shift-&gt;ymd},</strong>
517 }
518);
519# Automatic see: DBIx::Class::InflateColumn::DateTime
520# Automatic see: DBIx::Class::InflateColumn::DateTime
521# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
522 </div>
523
524 <div class="slide">
525 <h1>Result:: (deflating)</h1>
526<pre>$book-&gt;date_published(DateTime-&gt;now);
527$book-&gt;update;</pre>
528 </div>
529
530 <div class="slide">
531 <h1>Result:: (inflating)</h1>
532<pre>my $date_published = $book-&gt;date_published;
533print $date_published-&gt;month_abbr;</pre>
534
535<strong><em>Nov</em></strong>
536 </div>
537
538 <div class="slide">
539 <h1>ResultSets::</h1>
41a0eb8e 540<pre>package Foo::Schema::ResultSet::Books;
52d980cb 541use base 'DBIx::Class::ResultSet';
542sub the_ultimate_books {
543 my $self = shift;
544 return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } });
545}
546sub by_author {
547 my ( $self, $author ) = @_;
548 return $self-&gt;search({ author =&gt; $author-&gt;id })
549}
550
5511;</pre>
552 </div>
553
554 <div class="slide">
555 <h1>ResultSets::</h1>
41a0eb8e 556<pre>package Foo::Schema::<strong>ResultSet::Books</strong>;
52d980cb 557use base '<strong>DBIx::Class::ResultSet</strong>';
558sub the_ultimate_books {
559 my $self = shift;
560 <strong>return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } })</strong>
561}
562sub by_author {
563 my ( $self, $author ) = @_;
564 return $self-&gt;search({ author =&gt; $author-&gt;id })
565}
566
5671;</pre>
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 <strong>return $self-&gt;search({ author =&gt; $author-&gt;id })</strong>
581}
582
5831;</pre>
584 </div>
585
586 <div class="slide">
587 <h1>ResultSets::</h1>
41a0eb8e 588<pre>use Foo::Schema;
589my $book_model = Foo::Schema-&gt;resultset('Books');
52d980cb 590my $book_rs = $book_model-&gt;the_ultimate_books;
591my @books = $book_rs-&gt;all;</pre>
592 </div>
593
594 <div class="slide">
595 <h1>ResultSets::chaining</h1>
41a0eb8e 596<pre>use Foo::Schema;
597my $book_model = Foo::Schema-&gt;resultset('Books');
598my $author_model = Foo::Schema-&gt;resultset('Authors');
52d980cb 599my $author = $author_model-&gt;search({ name =&gt; 'Douglas Adams' })-&gt;single;
600my $book_rs = $book_model-&gt;the_ultimate_books-&gt;by_author($author);
601my @books = $book_rs-&gt;all;</pre>
602 </div>
603
604 <div class="slide">
605 <h1>ResultSets::chaining</h1>
606<pre>my $book_rs = $book_model
607 -&gt;the_ultimate_books
608 -&gt;by_author($author);</pre>
609or
610
611<pre>my $book_rs = $book_model
612 -&gt;the_ultimate_books();
613$book_rs = $book_rs-&gt;by_author($author);</pre>
614<pre># Debug (SQL):
615
616# SELECT me.id, me.title, me.date_published, me.author
617# FROM books me
618# WHERE ( ( ( author = ? ) AND ( title LIKE ? ) ) ): '5', '%42%'
619# WHERE ( ( ( author = ? ) AND ( title LIKE ? ) ) ): '5', '%42%'</pre>
620 </div>
621
622 <div class="slide">
623 <h1>ResultSets::chaining</h1>
624<pre>my $rs = $book_model
625 -&gt;category('childrens')
626 -&gt;by_author($author)
627 -&gt;published_after('1812')
628 -&gt;first_page_contains('once upon')
629 -&gt;rating_greater_than(4);
630
631my @books = $rs-&gt;all;</pre>
632 </div>
633
634 <div class="slide">
635 <h1>overloading before new record</h1>
636 </div>
637
638 <div class="slide">
639 <h1>overloading before new record</h1>
41a0eb8e 640 <pre>package Foo::Schema::Result::Authors;
52d980cb 641use base 'DBIx::Class';
642
643sub new {
644 my ( $class, $attrs ) = @_;
645 # Mess with $attrs
646 my $new = $class-&gt;next::method($attrs);
647 return $new
648}
649
6501;</pre>
651
652 <div class="slide">
653 <h1>relationships</h1>
654 </div>
655
656 <div class="slide">
657 <h1>multiple authors</h1>
658 </div>
659
660 <div class="slide">
661 <h1>a few relationships</h1>
662 (authors -- author_link_to_book -- books)
663 </div>
664
665 <div class="slide">
666 <h1>a few relationships</h1>
667 !
668 </div>
669
670 <div class="slide">
671 <h1>new join table</h1>
672<pre>CREATE TABLE author_and_books(
673 id int(8) primary key auto_increment,
674 book int(8),
675 author int(8),
676 foreign key (book) references books(id),
677 foreign key (author) references authors(id)
678) engine = InnoDB DEFAULT CHARSET=utf8;
679
680ALTER TABLE `books` DROP `author`</pre>
681 </div>
682
683 <div class="slide">
684 <h1>new join table</h1>
685<pre>CREATE TABLE author_and_books(
686 id int(8) primary key auto_increment,
687 book int(8),
688 author int(8),
689 <strong>foreign key (book) references books(id),
690 foreign key (author) references authors(id)</strong>
691) engine = InnoDB DEFAULT CHARSET=utf8;
692
693ALTER TABLE `books` DROP `author`</pre>
694 </div>
695
696 <div class="slide">
697 <h1>has_many</h1>
698 </div>
699
700 <div class="slide">
701 <h1>has_many</h1>
41a0eb8e 702<pre>package Foo::Schema::<strong>Result::Books</strong>;
52d980cb 703
41a0eb8e 704__PACKAGE__-&gt;has_many( author_and_books =&gt; "Foo::Schema::Result::AuthorAndBooks",
52d980cb 705 { "foreign.book" =&gt; "self.id" },
706);
707
708<strong># This is auto generated by Schema::Loader</strong></pre>
709 </div>
710
711 <div class="slide">
712 <h1>has_many</h1>
41a0eb8e 713<pre>package Foo::Schema::<strong>Result::Books</strong>;
52d980cb 714
715__PACKAGE__-&gt;has_many(
716author_and_books =&gt; <strong># name of accessor</strong>
41a0eb8e 717"Foo::Schema::Result::AuthorAndBooks", <strong># related class</strong>
52d980cb 718 { "foreign.book" =&gt; "self.id" } <strong># Relationship (magic often works if not
719 # specified, but avoid!)</strong>
720);
721</pre>
722 </div>
723
724 <div class="slide">
725 <h1>belongs_to</h1>
726 </div>
727
728 <div class="slide">
729 <h1>belongs_to</h1>
41a0eb8e 730<pre>package Foo::Schema::<strong>Result::AuthorAndBooks</strong>;
52d980cb 731
732__PACKAGE__-&gt;belongs_to(
733 book =&gt; <strong># Accessor name</strong>
41a0eb8e 734 "Foo::Schema::Result::Books", <strong># Related class</strong>
52d980cb 735 { id =&gt; "book" } <strong># relationship</strong>
736);
737</pre>
738 </div>
739
740 <div class="slide">
741 <h1>same for Authors</h1>
742 </div>
743
744 <div class="slide">
745 <h1>with no coding...</h1>
746 </div>
747
748 <div class="slide">
749 <h1>many_to_many</h1>
750 </div>
751
752 <div class="slide">
753 <h1>many_to_many</h1>
41a0eb8e 754 <pre>package Foo::Schema::<strong>Result::Books</strong>;
52d980cb 755use base 'DBIx::Class';
756
757__PACKAGE__-&gt;many_to_many(
758 authors =&gt; "author_and_books", 'author'
759);
760
7611;
762
763<strong> # This is <em>NOT</em> auto generated by Schema::Loader </strong></pre>
764 </div>
765
766 <div class="slide">
767 <h1>many_to_many</h1>
41a0eb8e 768 <pre>package Foo::Schema::<strong>Result::Books</strong>;
52d980cb 769use base 'DBIx::Class';
770
771__PACKAGE__-&gt;many_to_many(
772 authors <strong># Accessor name</strong>
773 =&gt; "author_and_books", <strong># has_many</strong>
774 'author' <strong># foreign relationship name</strong>
775);
776
7771;</pre>
778 </div>
779
780 <div class="slide">
781 <h1>many_to_many</h1>
41a0eb8e 782 <pre>package Foo::Schema::Result::Authors;
52d980cb 783use base 'DBIx::Class';
784
785__PACKAGE__-&gt;many_to_many(
786 "books" <strong># Accessor Name</strong>
787 =&gt; "author_and_books", <strong># has_many accessor_name</strong>
788 'book' <strong># foreign relationship name</strong>
789);
790
7911;
792
793<strong># This is <em>NOT</em> auto generated by Schema::Loader</strong></pre>
794 </div>
795
796 <div class="slide">
797 <h1>using many_to_many</h1>
798 <pre>#!/usr/bin/perl
799
41a0eb8e 800use Foo::Schema;
52d980cb 801
41a0eb8e 802my $author_model = Foo::Schema-&gt;resultset('Authors');
52d980cb 803my $author = $author_model-&gt;search({
804 name =&gt; 'Douglas Adams',
805})-&gt;single;
806$author-&gt;add_to_books({
807 title =&gt; 'A new book',
808});</pre>
809 </div>
810
811 <div class="slide">
812 <h1>using many_to_many</h1>
813 <pre>my $author = $author_model-&gt;search({
814 name =&gt; 'Douglas Adams',
815})-&gt;single;
816<strong>$author-&gt;add_to_books({
817 title =&gt; 'A new book',
818});</strong>
819
820# SELECT me.id, me.name FROM authors me
821# WHERE ( name = ? ): 'Douglas Adams';
822# INSERT INTO books (title) VALUES (?): 'A new book';
823# INSERT INTO author_and_books (author, book)
824# VALUES (?, ?): '5', '2';</pre>
825 </div>
826
827 <div class="slide">
828 <h1>using many_to_many</h1>
829 <pre>$author-&gt;add_to_books($book);
830
831$book-&gt;add_to_authors($author_1);
832$book-&gt;add_to_authors($author_2);</pre>
833 </div>
834
835 <div class="slide">
836 <h1>in 16 lines of code</h1>
837 </div>
838
839 <div class="slide">
840 <h1>errors</h1>
841 <p>Read them closely!</p>
842 </div>
843
844 <div class="slide">
845 <h1>error messages</h1>
41a0eb8e 846 <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 847 </div>
848
849 <div class="slide">
850 <h1>error messages</h1>
41a0eb8e 851 <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 852 </div>
853
854 <div class="slide">
855 <h1>errors</h1>
856 <ul>
857 <li>Turn on debugging</li>
858 <li>Read error messages (sometimes useful!)</li>
859 <li>Check field names</li>
860 <li>Check package names</li>
861 <li>Check which database you are connected to (dev/test/live?) - repeat above</li>
862 </ul>
863 </div>
864
865 <div class="slide">
866 <h1>bonus slides!</h1>
867 </div>
868
869 <div class="slide">
870 <h1>Template Toolkit</h1>
871 <ul>
872 <li><pre>[% author.books.count %]</pre> not working?</li>
873 <li>TT all methods are called in list context</li>
874 <li><pre>[% author.books<strong>_rs</strong>.count %]</pre> scalar context</li>
875 <li><em>Available for all relationships</em></li>
876 </ul>
877 </div>
878
879 <div class="slide">
880 <h1>Catalyst</h1>
0cffcad7 881 <pre>package Your::App::Model::<strong>Foo</strong>;
41a0eb8e 882use base qw(<strong>Catalyst::Model::Schema::Schema</strong>);
52d980cb 883
884use strict;
885use warnings;
886
887__PACKAGE__-&gt;config(
41a0eb8e 888 schema_class =&gt; '<strong>Foo::Schema</strong>',
52d980cb 889);
890
8911;</pre>
892 <p>Keep your Schema in a <em>separate</em> package to your Catalyst application</p>
893 </div>
894
895 <div class="slide">
896 <h1>Catalyst</h1>
897<pre>sub action_name : Local {
898 my ($self, $c) = @_;
899
41a0eb8e 900 my $model = $c-&gt;model('Schema::Foo');
52d980cb 901 my $author_model = $model-&gt;resultset('Authors');
902
903}
904
9051;</pre>
906 </div>
907
908</div>
909</body>
910</html>