add doc links
[dbsrgits/dbix-class-introduction-presentation.git] / slideshow.html
index 68f2a07..8ad9bce 100644 (file)
    <div class="slide">
       <h1>Authors</h1>
       <h4>Originally Leo Lapworth @ LPW 2009</h4>
-      <h4>Matthew S. Trout</h4>
-      <h4>Arthur Axel "fREW" Schmidt</h4>
+      <h4>Amiri Barksdale</h4>
       <h4>Justin D. Hunter</h4>
+      <h4>Arthur Axel "fREW" Schmidt</h4>
    </div>
 
    <div class="slide">
-      <h1>assumptions</h1>
-      <p>You know a little about Perl and using objects</p>
-      <p>You know a little bit about databases and using foreign keys</p>
+      <h1>What's up guys?</h1>
       <div class="notes">
          <ul>
-            <li>How many people have designed a database with Foreign Keys?</li>
             <li>How many people have used any ORM?<ul>
                <li>In Perl?<ul>
                   <li>DBIC?</li>
-                  <li> Class::DBI? </li>
-                  <li> Rose::DB?  </li>
-                  <li> Fey?  </li>
-                  <li> Others?  </li>
+                  <li>Class::DBI?</li>
+                  <li>Rose::DB?</li>
+                  <li>Fey?</li>
+                  <li>Others?</li>
                </ul></li>
-               <li>AR? </li>
-               <li> DataMapper?  </li>
+               <li>AR?</li>
+               <li>DataMapper?</li>
                <li>(N)Hibernate?</li>
             </ul></li>
          </ul>
    </div>
 
    <div class="slide">
+      <h1>Purpose</h1>
+      <p>The purpose of this talk is to show you as many features of
+      DBIx::Class in 40 minutes so that when you need to do something with
+      it later you will know what's possible</p>
+      <ul class="incremental">
+         <li>Note: links in slides are so you can find docs for what I'm talking about later</li>
+      </ul>
+   </div>
+
+   <div class="slide">
       <h1>DBIx::Class?</h1>
       <ul>
          <li>ORM (object relational mapper)</li>
          <li>SQL &lt;-&gt; OO (using objects instead of SQL)</li>
-         <li>Simple, powerful, complex, fab and confusing</li>
          <li>There are many ORMs, DBIx::Class just happens to be the best in Perl (personal opinion)</li>
       </ul>
    </div>
 
    <div class="slide">
-      <h1>why this talk?</h1>
-      <ul>
-         <li>Help avoid mistakes I made!</li>
-         <li>Help learn DBIx::Class faster</li>
-         <li>Make your coding easier</li>
-      </ul>
+      <h1>Meta</h1>
+      <p>These are reasons that are not technical or inherent to
+      the code of DBIC, but are totally awesome things about it.</p>
    </div>
 
    <div class="slide">
-      <h1>point of note</h1>
-      <p><em>"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." - Brian W. Kernighan</em></p>
-      <p>This talk is about making it easy so we are less likely to get confused</p>
+      <h1>Large Community</h1>
+      <p>Currently there are 88 people listed as contributors to DBIC.  That
+      ranges from documentation help, to test help, to added features,
+      to entire database support.</p>
    </div>
 
    <div class="slide">
-      <h1>table setup</h1>
+      <h1>Active Community</h1>
+      <p>Currently (June 9, 2010) 6 active branches (commited to in the last two weeks) in git.  Last release (0.08122) had 14 new features, and 16 bug fixes.  Of course that <a href="http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits/DBIx-Class.git;a=blob;f=Changes">ebbs and flows</a>.</p>
    </div>
 
    <div class="slide">
-      <h1>example...</h1>
-      <ul>
-         <li>Authors</li>
-         <li>Books</li>
+      <h1>Responsive Community</h1>
+      <ul class="incremental">
+         <li>needed MSSQL order-by support, they helped me add support</li>
+         <li>generally very welcoming of people willing to help</li>
       </ul>
    </div>
 
    <div class="slide">
-      <h1>authors table</h1>
-<pre>CREATE TABLE authors(
-   id   int(8) primary key auto_increment,
-   name varchar(255)
-) engine = InnoDB DEFAULT CHARSET=utf8;</pre>
-   </div>
-
-   <div class="slide">
-      <h1>tips</h1>
-      <p>Name tables as simple plurals (<strong>add an S</strong>) - makes relationships easier to understand</p>
-      <p>(issue: Matt Trout "Tables should not be plural as gives you plurals for Result:: package names which represent a single row" - talk may be rewritten in future to reflect this as this is better once you understand the relationship setup - either way, consistency is important)</p>
-      <p>Use a character set (<strong>UTF8</strong>) from the start (for international characters)</p>
-   </div>
-
-   <div class="slide">
-      <h1>authors table</h1>
-<pre>CREATE TABLE author<strong>s</strong>(
-   id   int(8) primary key auto_increment,
-   name varchar(255)
-) engine = <strong>InnoDB</strong> DEFAULT CHARSET=<strong>utf8</strong>;</pre>
-   </div>
-
-   <div class="slide">
-      <h1>books table</h1>
-<pre>CREATE TABLE books(
-   id     int(8) primary key auto_increment,
-   title  varchar(255),
-   author int(8),foreign key (author)
-      references authors(id)
-) engine = InnoDB DEFAULT CHARSET=utf8;</pre>
+      <h1>General ORM</h1>
+      <p>These are things that are in most other ORMs, but are still reasons
+      to use DBIC over raw SQL.</p>
    </div>
 
-
    <div class="slide">
-      <h1>tips</h1>
-      <p>Name link fields as singular</p>
-      <p>Check foreign key is the same field and type and size in both tables</p>
+      <h1>Cross DB</h1>
+      <p>The vast majority of code should run on all databases without needing tweaking</p>
    </div>
 
    <div class="slide">
-      <h1>books table</h1>
-<pre>CREATE TABLE books(
-   id     int(8) primary key auto_increment,
-   title  varchar(255),
-   author <strong>int(8)</strong>,<strong>foreign key (<em>author</em>)</strong>
-      <strong>references <em>authors(id)</em></strong>
-) engine = InnoDB DEFAULT CHARSET=utf8;</pre>
-   </div>
-
-   <div class="slide">
-      <h1>CRUD compared</h1>
-      <ul>
+      <h1>Basic CRUD</h1>
+      <ul class="incremental">
          <li><strong>C</strong> - Create</li>
          <li><strong>R</strong> - Read</li>
          <li><strong>U</strong> - Update</li>
    </div>
 
    <div class="slide">
-      <h1>Manual (SQL)</h1>
-   </div>
-
-   <div class="slide">
-      <h1>manual: create</h1>
+      <h1>SQL: Create</h1>
 <pre>my $sth = $dbh-&gt;prepare('
    INSERT INTO books
-   (title, author)
+   (title, author_id)
    values (?,?)
 ');
 
@@ -219,20 +181,20 @@ $sth-&gt;execute(
    </div>
 
    <div class="slide">
-      <h1>manual: create</h1>
-<pre>my $sth = $dbh-&gt;prepare('
-   <strong>INSERT INTO books
-   (title, author)
-   values (?,?)</strong>
-');
-
-$sth-&gt;execute(
-  'A book title', <strong><em>$author_id</em></strong>
-);</pre>
+      <h1>DBIC: Create</h1>
+<pre>my $book = $book_rs-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#create">create</a>({
+   title     =&gt; 'A book title',
+   author_id =&gt; $author_id,
+});</pre>
+      <ul class="incremental">
+         <li>No need to pair placeholders and values</li>
+         <li>Automatically gets autoincremented id for you</li>
+         <li>Transparrently uses INSERT ... RETURNING for databases that support it</li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>manual: retrieve</h1>
+      <h1>SQL: Read</h1>
 <pre>my $sth = $dbh-&gt;prepare('
    SELECT title,
    authors.name as author_name
@@ -242,7 +204,7 @@ $sth-&gt;execute(
    </div>
 
    <div class="slide">
-      <h1>manual: retrieve</h1>
+      <h1>SQL: Read</h1>
 <pre>while( my $book = $sth-&gt;fetchrow_hashref() ) {
   print 'Author of '
      . $book-&gt;{title}
@@ -253,103 +215,24 @@ $sth-&gt;execute(
    </div>
 
    <div class="slide">
-      <h1>manual: update</h1>
-<pre>my $update = $dbh-&gt;prepare('
-   UPDATE books
-   SET title = ?
-   WHERE id = ?
-');
-
-$update-&gt;execute(
-  'New title',<strong>$book_id</strong>
-);</pre>
-   </div>
-
-   <div class="slide">
-      <h1>manual: delete</h1>
-<pre>my $delete = $dbh-&gt;prepare('
-   DELETE FROM books
-   WHERE id = ?
-');
+      <h1>DBIC: Read</h1>
+<pre>my $book = $book_rs-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#find">find</a>($book_id);
 
-$delete-&gt;execute(<strong>$book_id</strong>);</pre>
-   </div>
-
-   <div class="slide">
-      <h1>DBIx::Class</h1>
-   </div>
-
-   <div class="slide">
-      <h1>DBIC: create</h1>
-<pre>my $book = $book_model-&gt;create({
-   title  =&gt; 'A book title',
-   author =&gt; $author_id,
-});</pre>
-      <p>Look ma, no SQL!</p>
-      <p><strong>Tip:</strong> do not pass in primary_key field, even if it's empty/undef as the object returned will have an empty id, even if your field is auto increment.</p>
-   </div>
-
-   <div class="slide">
-      <h1>DBIC: create</h1>
-<pre>my $book = $book_model-&gt;create({
-   title  =&gt; 'A book title',
-   author =&gt; <strong>$author_id</strong>,
-});</pre>
-   </div>
-
-   <div class="slide">
-      <h1>DBIC: create</h1>
-<pre>my $pratchett = $author_model-&gt;create({
-   name =&gt; 'Terry Pratchett',
-});</pre>
-   </div>
-
-   <div class="slide">
-      <h1>DBIC: create</h1>
-<pre>my $book = $pratchett-&gt;create_related(
-  books =&gt; {
-   title =&gt; 'Another Discworld book',
-});</pre>
-<strong>or</strong>
-<pre>my $book = $pratchett-&gt;add_to_books({
-   title =&gt; 'Another Discworld book',
-});</pre>
-   </div>
-
-   <div class="slide">
-      <h1>DBIC: create</h1>
-<pre>my $book = $pratchett-&gt;create_related(
-  <strong>books</strong> =&gt; {
-   title =&gt; 'Another Discworld book',
-});</pre>
-<strong>or</strong>
-<pre>my $book = $pratchett-&gt;add_to_<strong>books</strong>({
-   title =&gt; 'Another Discworld book',
-});</pre>
-   </div>
-
-   <div class="slide">
-      <h1>DBIC: retrieve</h1>
-      <p>DBIx::Class - Lots of ways to do the same thing...</p>
-      <p><em>"There is more than one way to do it (TIMTOWTDI, usually pronounced "Tim Toady") is a Perl motto"</em></p>
-   </div>
-
-   <div class="slide">
-      <h1>DBIC: retrieve</h1>
-<pre>my $book = $book_model-&gt;find($book_id);
-
-my $book = $book_model-&gt;search({
+my $book = $book_rs-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#search">search</a>({
    title =&gt; 'A book title',
-})-&gt;single;
+}, { rows =&gt; 1 })-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#next">next</a>;
 
-my @books = $book_model-&gt;search({
+my @books = $book_rs-&gt;search({
    author =&gt; $author_id,
-})-&gt;all;</pre>
+})-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#all">all</a>;</pre>
+      <ul class="incremental">
+         <li>TMTOWTDI</li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>DBIC: retrieve</h1>
-<pre>while( my $book = $books_rs-&gt;next() ) {
+      <h1>DBIC: Read</h1>
+<pre>while( my $book = $books_rs-&gt;next ) {
  print 'Author of '
     . $book-&gt;title
     . ' is '
@@ -359,584 +242,453 @@ my @books = $book_model-&gt;search({
    </div>
 
    <div class="slide">
-      <h1>DBIC: retrieve</h1>
-<pre>my $books_rs = $book_model-&gt;search({
-   author =&gt; $author_id,
-});</pre>
-      <p>Search takes SQL::Abstract formatted queries</p>
-      <pre>&gt; perldoc SQL::Abstract</p>
+      <h1>SQL: Update</h1>
+<pre>my $update = $dbh-&gt;prepare('
+   UPDATE books
+   SET title = ?
+   WHERE id = ?
+');
+
+$update-&gt;execute(
+  'New title',<strong>$book_id</strong>
+);</pre>
    </div>
 
    <div class="slide">
-      <h1>DBIC: update</h1>
-<pre>$book-&gt;update({
+      <h1>DBIC: Update</h1>
+<pre>$book-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Row#update">update</a>({
   title =&gt; 'New title',
 });</pre>
+      <ul class="incremental">
+         <li>Lazy Update</li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>DBIC: delete</h1>
-<pre>$book-&gt;delete;</pre>
-   </div>
-
-   <div class="slide">
-      <h1>Creating models</h1>
-   </div>
+      <h1>SQL: Delete</h1>
+<pre>my $delete = $dbh-&gt;prepare('
+   DELETE FROM books
+   WHERE id = ?
+');
 
-   <div class="slide">
-      <pre>Example of a DBIC Result</pre>
+$delete-&gt;execute(<strong>$book_id</strong>);</pre>
    </div>
 
    <div class="slide">
-      <pre>Example of a DBIC Result</pre>
+      <h1>DBIC: Delete</h1>
+<pre>$book-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Row#delete">delete</a>;</pre>
    </div>
 
    <div class="slide">
-      <p>too much typing!  too much maintenance!</p>
-      <p>too much maintenance!</p>
+      <h1>OO Overidability</h1>
+      <ul class="incremental">
+         <li>Override new if you want to do validation</li>
+         <li>Override delete if you want to disable deletion</li>
+         <li>and on and on</li>
+      </ul>
+      <div class="notes">
+         <p>I got yelled at about this before by people, so
+         we don't get EVERYTHING from OO, but we do get a lot
+         so :-P</p>
+      </div>
    </div>
 
    <div class="slide">
-      <h1>Schema::Loader</h1>
-      <pre>code for S::L here</pre>
+      <h1>Convenience Methods</h1>
+      <ul class="incremental">
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#find_or_create">find_or_create</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#update_or_create">update_or_create</a></li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>splitting logic cleanly</h1>
-      <p>Foo::Schema::Result::Foo = an individual row</p>
-      <p>Foo::Schema::ResultSet::Foo = searches / results</p>
+      <h1>Non-column methods</h1>
+      <p>Need a method to get a user's gravatar URL?  Add a
+      gravatar_url method to their Result class</p>
    </div>
 
    <div class="slide">
-      <h1>using your Schema</h1>
-      <pre>example usage code goes here</pre>
+      <h1>RELATIONSHIPS</h1>
+      <ul class="incremental">
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Relationship#belongs_to">belongs_to</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Relationship#has_many">has_many</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Relationship#might_have">might_have</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Relationship#has_one">has_one</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Relationship#many_to_many">many_to_many</a> (technically not a relationship)</li>
+         <li>SET AND FORGET</li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>DEBUGGING</h1>
-      <pre>DBIC_TRACE=1 ./your_script.pl</pre>
+      <h1>DBIx::Class Specific Features</h1>
+      <p>These things may be in other ORM's, but they are very specific, so doubtful</p>
    </div>
 
    <div class="slide">
-      <h1>Schema::Loader</h1>
-<pre>Foo::Schema::Result::Authors-&gt;table("authors");
-Foo::Schema::Result::Authors-&gt;add_columns(
-   id =&gt; {
-      data_type     =&gt; "INT",
-      default_value =&gt; undef,
-      is_nullable   =&gt; 0,
-      size          =&gt; 8
-   },
-   title =&gt; {
-      data_type     =&gt; "VARCHAR",
-      default_value =&gt; undef,
-      is_nullable   =&gt; 1,
-      size          =&gt; 255,
-   },
+      <h1>-&gt;deploy</h1>
+      <p>Perl -&gt; DB</p>
+<pre>my $schema = Foo::Schema-&gt;connect(
+   $dsn, $user, $pass
 );
-Foo::Schema::Result::Authors-&gt;set_primary_key("id");</pre>
+$schema-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#deploy">deploy</a>
+</pre>
+<p>See also: <a href="http://search.cpan.org/perldoc?DBIx::Class::DeploymentHandler">DBIx::Class::DeploymentHandler</a></p>
    </div>
 
    <div class="slide">
       <h1>Schema::Loader</h1>
-<pre>Foo::Schema::Result::Books->table("books");
-Foo::Schema::Result::Books->add_columns(
-   id =&gt; {
-      data_type     =&gt; "INT",
-      default_value =&gt; undef,
-      is_nullable   =&gt; 0,
-      size          =&gt; 8
-   },
-   name =&gt; {
-      data_type     =&gt; "VARCHAR",
-      default_value =&gt; undef,
-      is_nullable   =&gt; 1,
-      size          =&gt; 255,
-   },
-   author =&gt; {
-      data_type     =&gt; "INT",
-      default_value =&gt; undef,
-      is_nullable   =&gt; 1,
-      size          =&gt; 8
-   },
-);
-Foo::Schema::Result::Books-&gt;set_primary_key("id");</pre>
-   </div>
+      <p>DB -&gt; Perl</p>
+<pre>package Foo::Schema;
+use strict; use warnings;
+use base '<a href="http://search.cpan.org/perldoc?DBIx::Class::Schema::Loader">DBIx::Class::Schema::Loader</a>';
+__PACKAGE__-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Schema::Loader::Base#CONSTRUCTOR_OPTIONS">loader_options</a>({
+   naming =&gt; 'v7',
+   debug  =&gt; $ENV{DBIC_TRACE},
+});
+1;
 
-   <div class="slide">
-      <h1>Schema::Loader</h1>
-<pre>Foo::Schema::Result::Authors-&gt;has_many(books =&gt; "Foo::Schema::Books",
-   { "foreign.author" =&gt; "self.id" });
+# elsewhere...
 
-Foo::Schema::Result::Books-&gt;belongs_to(author =&gt; "Foo::Schema::Authors",
-   { id =&gt; "author" });</pre>
+my $schema = Foo::Schema-&gt;connect(
+   $dsn, $user, $pass
+);
+</pre>
    </div>
 
    <div class="slide">
-      <h1>SQL - debugging</h1>
-<pre>INSERT INTO authors (name)
-   VALUES (?): 'Douglas Adams'
-
-INSERT INTO books (author, title)
-   VALUES (?, ?): '5', '42'</pre>
+      <h1>Populate</h1>
+      <p>Made for inserting lots of rows very quicky into database</p>
+<pre>$schema-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#populate">populate</a>([ Users =&gt;
+   [qw( username password )],
+   [qw( frew     &gt;=4char$ )],
+   [qw(      ...          )],
+   [qw(      ...          )],
+);
+</pre>
+      <ul class="incremental">
+         <li>I use this to <a href="http://blog.afoolishmanifesto.com/archives/1255">export our whole (200M~) db to SQLite</a></li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>overloading</h1>
-<pre>Foo::Schema::Result::Books
-Foo::Schema::ResultSet::Books
-Foo::Schema::Result::Authors
-Foo::Schema::ResultSet::Books</pre>
+      <h1>Multicreate</h1>
+      <p>Create an object and all of it's related objects all at once</p>
+<pre>$schema-&gt;resultset('Author')-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#create">create</a>({
+   name =&gt; 'Stephen King',
+   books =&gt; [{ title =&gt; 'The Dark Tower' }],
+   address =&gt; {
+      street =&gt; '123 Turtle Back Lane',
+      state  =&gt; { abbreviation =&gt; 'ME' },
+      city   =&gt; { name =&gt; 'Lowell'     },
+   },
+});
+</pre>
+      <div class="notes">
+         <ul>
+            <li>books is a has_many</li>
+            <li>address is a belongs_to which in turn belongs to state and city each</li>
+            <li>for this to work right state and city must mark abbreviation and name as unique</li>
+         </ul>
+      </div>
    </div>
 
    <div class="slide">
-      <h1>Result::</h1>
-<pre>package Foo::Schema::Result::Books;
-use base 'DBIx::Class';
-use strict;
-use warnings;
-
-sub isbn {
-   my $self = shift;
-
-   # search amazon or something
-   my $api = Amazon::API-&gt;book({
-      title =&gt; $self-&gt;title
-   });
-
-   return $api-&gt;isbn;
-}
-
-1;</pre>
+      <h1>Extensible</h1>
+      <p>DBIx::Class helped pioneer fast MI in Perl 5 with Class::C3, so it is made
+      to allow extensions to nearly every part of it.</p>
    </div>
 
    <div class="slide">
-      <h1>Result::</h1>
-<pre>print $book-&gt;isbn;</pre>
+      <h1>Extensible: DBIC::Helpers</h1>
+      <ul class="incremental">
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::IgnoreWantarray">DBIC::Helper::ResultSet::IgnoreWantarray</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::Random">DBIC::Helper::ResultSet::Random</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::SetOperations">DBIC::Helper::ResultSet::SetOperations</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::JoinTable">DBIC::Helper::Row::JoinTable</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::NumifyGet">DBIC::Helper::Row::NumifyGet</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::SubClass">DBIC::Helper::Row::SubClass</a></li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::ToJSON">DBIC::Helper::Row::ToJSON</a></li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>Result:: (inflating)</h1>
-<pre>package Foo::Schema::Result::Books;
-use base 'DBIx::Class';
-use strict;
-use warnings;
-
-use DateTime::Format::MySQL;
-
-__PACKAGE__-&gt;<strong>inflate_column</strong>(
-   <strong>date_published</strong> =&gt; {
-      inflate =&gt; sub { DateTime::Format::MySQL-&gt;parse_date(shift) },
-      deflate =&gt; sub { shift-&gt;ymd},
-   }
-);
-# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
+      <h1>Extensible: <a href="http://search.cpan.org/perldoc?DBIx::Class::TimeStamp">DBIC::TimeStamp</a></h1>
+      <ul class="incremental">
+         <li>Cross DB</li>
+         <li>set_on_create</li>
+         <li>set_on_update</li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>Result:: (inflating)</h1>
-<pre>package Foo::Schema::Result::Books;
-use base 'DBIx::Class';
-use strict;
-use warnings;
-
-use DateTime::Format::MySQL;
-
-__PACKAGE__-&gt;inflate_column(
-   date_published =&gt; {
-      <strong>inflate =&gt; sub { DateTime::Format::MySQL-&gt;parse_date(shift) },
-      deflate =&gt; sub { shift-&gt;ymd},</strong>
-   }
-);
-# Automatic see: DBIx::Class::InflateColumn::DateTime
-# Automatic see: DBIx::Class::InflateColumn::DateTime
-# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
+      <h1>Extensible: Kioku</h1>
+      <ul class="incremental">
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Schema::KiokuDB">DBIx::Class::Schema::KiokuDB</a></li>
+         <li>Kioku is the new hotness</li>
+         <li>Mix RDBMS with Object DB</li>
+         <li>beta ( == sexy )</li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>Result:: (deflating)</h1>
-<pre>$book-&gt;date_published(DateTime-&gt;now);
-$book-&gt;update;</pre>
+      <h1><a href="http://search.cpan.org/perldoc?SQL::Abstract">SQL::Abstract</a></h1>
+<pre>my $resultset = $book_rs-&gt;search({
+   name =&gt; { -like =&gt; "%$nick%" },
+});</pre>
+      <ul class="incremental">
+         <li>(kinda) introspectible</li>
+         <li>Prettier than SQL</li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>Result:: (inflating)</h1>
-<pre>my $date_published = $book-&gt;date_published;
-print $date_published-&gt;month_abbr;</pre>
-
-<strong><em>Nov</em></strong>
+      <h1>Result vs ResultSet</h1>
+         <ul class="incremental">
+            <li>Result == Row</li>
+            <li>ResultSet == Query Plan<ul class="incremental">
+               <li>Internal Join Optimizer for all DB's (!!!)</li>
+            </ul></li>
+            <li>(less important but...)</li>
+            <li>ResultSource == Table</li>
+            <li>Storage == Database</li>
+         </ul>
    </div>
 
    <div class="slide">
-      <h1>ResultSets::</h1>
-<pre>package Foo::Schema::ResultSet::Books;
+      <h1><a href="http://search.cpan.org/perldoc?DBIx::Class::Manual::Cookbook#Predefined_searches">ResultSet methods</a></h1>
+<pre>package MyApp::Schema::ResultSet::Book;
 use base 'DBIx::Class::ResultSet';
-sub the_ultimate_books {
+sub good {
    my $self = shift;
-   return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } });
-}
-sub by_author {
-   my ( $self, $author ) = @_;
-   return $self-&gt;search({ author =&gt; $author-&gt;id })
-}
-
-1;</pre>
-   </div>
-
-   <div class="slide">
-      <h1>ResultSets::</h1>
-<pre>package Foo::Schema::<strong>ResultSet::Books</strong>;
-use base '<strong>DBIx::Class::ResultSet</strong>';
-sub the_ultimate_books {
+   $self-&gt;search({
+      $self-&gt;current_source_alias .
+         '.rating' =&gt; { '&gt;=' =&gt; 4 },
+   })
+};
+sub cheap {
    my $self = shift;
-   <strong>return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } })</strong>
-}
-sub by_author {
-   my ( $self, $author ) = @_;
-   return $self-&gt;search({ author =&gt; $author-&gt;id })
-}
-
-1;</pre>
-   </div>
-
-   <div class="slide">
-      <h1>ResultSets::</h1>
-<pre>package Foo::Schema::ResultSet::Books;
-use base 'DBIx::Class::ResultSet';
-sub the_ultimate_books {
-   my $self = shift;
-   return $self-&gt;search({ title =&gt; { -like =&gt; '%42%' } });
-}
-sub by_author {
-   my ( $self, $author ) = @_;
-   <strong>return $self-&gt;search({ author =&gt; $author-&gt;id })</strong>
-}
-
-1;</pre>
-   </div>
-
-   <div class="slide">
-      <h1>ResultSets::</h1>
-<pre>use Foo::Schema;
-my $book_model = Foo::Schema-&gt;resultset('Books');
-my $book_rs    = $book_model-&gt;the_ultimate_books;
-my @books      = $book_rs-&gt;all;</pre>
-   </div>
-
-   <div class="slide">
-      <h1>ResultSets::chaining</h1>
-<pre>use Foo::Schema;
-my $book_model   = Foo::Schema-&gt;resultset('Books');
-my $author_model = Foo::Schema-&gt;resultset('Authors');
-my $author       = $author_model-&gt;search({ name =&gt; 'Douglas Adams' })-&gt;single;
-my $book_rs      = $book_model-&gt;the_ultimate_books-&gt;by_author($author);
-my @books        = $book_rs-&gt;all;</pre>
-   </div>
-
-   <div class="slide">
-      <h1>ResultSets::chaining</h1>
-<pre>my $book_rs = $book_model
-  -&gt;the_ultimate_books
-  -&gt;by_author($author);</pre>
-or
-
-<pre>my $book_rs = $book_model
-  -&gt;the_ultimate_books();
-$book_rs = $book_rs-&gt;by_author($author);</pre>
-<pre># Debug (SQL):
-
-# SELECT me.id, me.title, me.date_published, me.author
-#   FROM books me
-#   WHERE ( ( ( author = ? ) AND ( title LIKE ? ) ) ): '5', '%42%'
-#   WHERE ( ( ( author = ? ) AND ( title LIKE ? ) ) ): '5', '%42%'</pre>
-   </div>
-
-   <div class="slide">
-      <h1>ResultSets::chaining</h1>
-<pre>my $rs = $book_model
-  -&gt;category('childrens')
-  -&gt;by_author($author)
-  -&gt;published_after('1812')
-  -&gt;first_page_contains('once upon')
-  -&gt;rating_greater_than(4);
-
-my @books = $rs-&gt;all;</pre>
-   </div>
-
-   <div class="slide">
-      <h1>overloading before new record</h1>
-   </div>
-
-   <div class="slide">
-      <h1>overloading before new record</h1>
-      <pre>package Foo::Schema::Result::Authors;
-use base 'DBIx::Class';
-
-sub new {
-   my ( $class, $attrs ) = @_;
-   # Mess with $attrs
-   my $new = $class-&gt;next::method($attrs);
-   return $new
-}
-
-1;</pre>
-
-   <div class="slide">
-      <h1>relationships</h1>
-   </div>
-
-   <div class="slide">
-      <h1>multiple authors</h1>
-   </div>
-
-   <div class="slide">
-      <h1>a few relationships</h1>
-      (authors -- author_link_to_book -- books)
-   </div>
-
-   <div class="slide">
-      <h1>a few relationships</h1>
-      !
-   </div>
-
-   <div class="slide">
-      <h1>new join table</h1>
-<pre>CREATE TABLE author_and_books(
-  id      int(8)    primary key auto_increment,
-  book    int(8),
-  author  int(8),
-  foreign key (book)     references books(id),
-  foreign key (author)   references authors(id)
-) engine = InnoDB DEFAULT CHARSET=utf8;
-
-ALTER TABLE `books` DROP `author`</pre>
-   </div>
-
-   <div class="slide">
-      <h1>new join table</h1>
-<pre>CREATE TABLE author_and_books(
-  id      int(8)    primary key auto_increment,
-  book    int(8),
-  author  int(8),
-  <strong>foreign key (book)     references books(id),
-  foreign key (author)   references authors(id)</strong>
-) engine = InnoDB DEFAULT CHARSET=utf8;
-
-ALTER TABLE `books` DROP `author`</pre>
+   $self-&gt;search({
+      $self-&gt;current_source_alias .
+         '.price' =&gt; { '&lt;=' =&gt; 5}
+   })
+};
+# ...
+1;
+      </pre>
    </div>
 
    <div class="slide">
-      <h1>has_many</h1>
+      <h1>ResultSet method notes</h1>
+      <ul class="incremental">
+         <li>All searches should be ResultSet methods</li>
+         <li>Name has obvious meaning</li>
+         <li><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#current_source_alias">current_source_alias</a> helps things to work no matter what</li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>has_many</h1>
-<pre>package Foo::Schema::<strong>Result::Books</strong>;
-
-__PACKAGE__-&gt;has_many( author_and_books =&gt; "Foo::Schema::Result::AuthorAndBooks",
-    { "foreign.book" =&gt; "self.id" },
-);
-
-<strong># This is auto generated by Schema::Loader</strong></pre>
+      <h1>ResultSet method in Action</h1>
+      <pre>$schema-&gt;resultset('Book')-&gt;good</pre>
    </div>
 
    <div class="slide">
-      <h1>has_many</h1>
-<pre>package Foo::Schema::<strong>Result::Books</strong>;
-
-__PACKAGE__-&gt;has_many(
-author_and_books =&gt; <strong># name of accessor</strong>
-"Foo::Schema::Result::AuthorAndBooks", <strong># related class</strong>
-    { "foreign.book" =&gt; "self.id" } <strong># Relationship (magic often works if not
-                                        # specified, but avoid!)</strong>
-);
+      <h1>ResultSet Chaining</h1>
+<pre>$schema-&gt;resultset('Book')
+   -&gt;good
+   -&gt;cheap
+   -&gt;recent
 </pre>
    </div>
 
    <div class="slide">
-      <h1>belongs_to</h1>
-   </div>
-
-   <div class="slide">
-      <h1>belongs_to</h1>
-<pre>package Foo::Schema::<strong>Result::AuthorAndBooks</strong>;
-
-__PACKAGE__-&gt;belongs_to(
-   book =&gt; <strong># Accessor name</strong>
-   "Foo::Schema::Result::Books", <strong># Related class</strong>
-   { id =&gt; "book" } <strong># relationship</strong>
-);
+      <h1>search_related</h1>
+<pre>my $score = $schema-&gt;resultset('User')
+   -&gt;search({'me.userid' =&gt; 'frew'})
+   -&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#related_resultset">related_resultset</a>('access')
+   -&gt;related_resultset('mgmt')
+   -&gt;related_resultset('orders')
+   -&gt;telephone
+   -&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#search_related">search_related</a>( shops =&gt; {
+      'shops.datecompleted' =&gt; {
+         -between =&gt; ['2009-10-01','2009-10-08']
+      }
+   })-&gt;completed
+   -&gt;related_resultset('rpt_score')
+   -&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#get_column">get_column</a>('raw_scores')
+   -&gt;first;
 </pre>
    </div>
 
    <div class="slide">
-      <h1>same for Authors</h1>
-   </div>
-
-   <div class="slide">
-      <h1>with no coding...</h1>
-   </div>
-
-   <div class="slide">
-      <h1>many_to_many</h1>
-   </div>
-
-   <div class="slide">
-      <h1>many_to_many</h1>
-      <pre>package Foo::Schema::<strong>Result::Books</strong>;
-use base 'DBIx::Class';
-
-__PACKAGE__-&gt;many_to_many(
-   authors =&gt; "author_and_books", 'author'
+      <h1>bonus rel methods</h1>
+<pre>my $book = $author-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Relationship::Base#create_related">create_related</a>(
+   <strong>books</strong> =&gt; {
+      title =&gt; 'Another Discworld book',
+   }
 );
 
-1;
-
-<strong> # This is <em>NOT</em> auto generated by Schema::Loader </strong></pre>
+my $book2 = $pratchett-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Relationship::Base#add_to_$rel">add_to_<strong>books</strong></a>({
+   title =&gt; 'MOAR Discworld book',
+});</pre>
+      <ul class="incremental">
+         <li>Automaticaly fills in foreign key for you</li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>many_to_many</h1>
-      <pre>package Foo::Schema::<strong>Result::Books</strong>;
-use base 'DBIx::Class';
+      <h1>Excellent Transaction Support</h1>
+<pre>$schema-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#txn_do">txn_do</a>(sub {
+   ...
+});
 
-__PACKAGE__-&gt;many_to_many(
-   authors <strong># Accessor name</strong>
-   =&gt; "author_and_books", <strong># has_many</strong>
-   'author' <strong># foreign relationship name</strong>
-);
+my $guard = $schema-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#txn_scope_guard">txn_scope_guard</a>;
+# ...
+$guard-&gt;commit;
 
-1;</pre>
+$schema-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#txn_begin">txn_begin</a>; # &lt;-- low level
+# ...
+$schema-&gt;<a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#txn_commit">txn_commit</a>;
+</pre>
    </div>
 
    <div class="slide">
-      <h1>many_to_many</h1>
-      <pre>package Foo::Schema::Result::Authors;
-use base 'DBIx::Class';
-
-__PACKAGE__-&gt;many_to_many(
-   "books" <strong># Accessor Name</strong>
-   =&gt; "author_and_books", <strong># has_many accessor_name</strong>
-   'book' <strong># foreign relationship name</strong>
+      <h1>InflateColumn</h1>
+<pre>package Foo::Schema::Result::Book;
+use base 'DBIx::Class::Core';
+use DateTime::Format::MySQL;
+# Result code here
+__PACKAGE__-&gt;load_components('<a href="http://search.cpan.org/perldoc?DBIx::Class::InflateColumn">InflateColumn</a>');
+__PACKAGE__-&gt;<strong><a href="http://search.cpan.org/perldoc?DBIx::Class::InflateColumn#inflate_column">inflate_column</a></strong>(
+   <strong>date_published</strong> =&gt; {
+      inflate =&gt; sub {
+         DateTime::Format::MySQL-&gt;parse_date(
+            shift
+         )
+      },
+      deflate =&gt; sub { shift-&gt;ymd },
+   },
 );
-
-1;
-
-<strong># This is <em>NOT</em> auto generated by Schema::Loader</strong></pre>
+# Automatic see: DBIC::InflateColumn::DateTime</pre>
    </div>
 
    <div class="slide">
-      <h1>using many_to_many</h1>
-      <pre>#!/usr/bin/perl
-
-use Foo::Schema;
-
-my $author_model = Foo::Schema-&gt;resultset('Authors');
-my $author       = $author_model-&gt;search({
-   name =&gt; 'Douglas Adams',
-})-&gt;single;
-$author-&gt;add_to_books({
-   title =&gt; 'A new book',
-});</pre>
+      <h1>InflateColumn: deflation</h1>
+<pre>$book-&gt;date_published(DateTime-&gt;now);
+$book-&gt;update;</pre>
    </div>
 
    <div class="slide">
-      <h1>using many_to_many</h1>
-      <pre>my $author = $author_model-&gt;search({
-   name =&gt; 'Douglas Adams',
-})-&gt;single;
-<strong>$author-&gt;add_to_books({
-   title =&gt; 'A new book',
-});</strong>
+      <h1>InflateColumn: inflation</h1>
+<pre>say $book-&gt;date_published-&gt;month_abbr;</pre>
 
-# SELECT me.id, me.name FROM authors me
-#     WHERE ( name = ? ): 'Douglas Adams';
-# INSERT INTO books (title) VALUES (?): 'A new book';
-# INSERT INTO author_and_books (author, book)
-#     VALUES (?, ?): '5', '2';</pre>
+<strong><em>Nov</em></strong>
    </div>
 
    <div class="slide">
-      <h1>using many_to_many</h1>
-      <pre>$author-&gt;add_to_books($book);
+      <h1>FilterColumn</h1>
+<pre>package Foo::Schema::Result::Book;
+use base 'DBIx::Class::Core';
+# Result code here
+__PACKAGE__-&gt;load_components('<a href="http://search.cpan.org/perldoc?DBIx::Class::FilterColumn">FilterColumn</a>');
 
-$book-&gt;add_to_authors($author_1);
-$book-&gt;add_to_authors($author_2);</pre>
-   </div>
+__PACKAGE__-&gt;<strong><a href="http://search.cpan.org/perldoc?DBIx::Class::FilterColumn#filter_column">filter_column</a></strong>(
+   <strong>length</strong> =&gt; {
+      to_storage   =&gt; 'to_metric',
+      from_storage =&gt; 'to_imperial',
+   },
+);
 
-   <div class="slide">
-      <h1>in 16 lines of code</h1>
+sub to_metric   { $_[1] * .305 }
+sub to_imperial { $_[1] * 3.28 }
    </div>
 
    <div class="slide">
-      <h1>errors</h1>
-      <p>Read them closely!</p>
+      <h1><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSetColumn">ResultSetColumn</a></h1>
+<pre>my $rsc = $schema-&gt;resultset('Book')
+   -&gt;get_column('price');
+$rsc-&gt;min;
+$rsc-&gt;max;
+$rsc-&gt;sum;
+</pre>
    </div>
 
    <div class="slide">
-      <h1>error messages</h1>
-      <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>
+      <h1>Aggregates</h1>
+<pre>my @res = $rs-&gt;search({}, {
+   <a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#select">select</a>   =&gt; [
+      'price',
+      'genre',
+      { max =&gt; price },
+      { avg =&gt; price },
+   ],
+   <a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#as">as</a>       =&gt; [
+      qw(price genre max_price avg_price)
+   ],
+   <a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#group_by">group_by</a> =&gt; [qw(price genre)],
+});
+for (@res) {
+   say $_-&gt;price . ' ' . $_-&gt;genre;
+   say $_-&gt;get_column('max_price');
+   say $_-&gt;get_column('min_price');
+}</pre>
    </div>
 
    <div class="slide">
-      <h1>error messages</h1>
-   <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>
+      <h1>Aggregates Notes</h1>
+      <ul class="incremental">
+         <li>Careful, get_column can basicaly mean THREE things</li>
+         <li>private for get what you should use an accessor for</li>
+         <li>public for what there is no accessor for</li>
+         <li>public for get resultset column (prev slide)</li>
+      </ul>
    </div>
 
    <div class="slide">
-      <h1>errors</h1>
-      <ul>
-         <li>Turn on debugging</li>
-         <li>Read error messages (sometimes useful!)</li>
-         <li>Check field names</li>
-         <li>Check package names</li>
-         <li>Check which database you are connected to (dev/test/live?) - repeat above</li>
+      <h1>HRI</h1>
+<pre>$rs-&gt;search({}, {
+  <a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#result_class">result_class</a> =&gt;
+    '<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultClass::HashRefInflator">DBIx::Class::ResultClass::HashRefInflator</a>',
+});</pre>
+      <ul class="incremental">
+         <li>Easy on memory</li>
+         <li>Mega fast</li>
+         <li>Great for quick debugging</li>
+         <li>Great for performance tuning (we went from 2m to &lt; 3s)</li>
       </ul>
    </div>
 
    <div class="slide">
-      <h1>bonus slides!</h1>
-   </div>
+      <h1><a href="http://search.cpan.org/perldoc?DBIx::Class::Manual::Cookbook#Subqueries">Subquery</a> Support</h1>
+<pre>my $inside_query = $schema-&gt;resultset('Artist')
+   -&gt;search({
+    name =&gt; [ 'Billy Joel', 'Brittany Spears' ],
+})-&gt;get_column('id')-&gt;as_query;
 
-   <div class="slide">
-      <h1>Template Toolkit</h1>
-      <ul>
-         <li><pre>[% author.books.count %]</pre> not working?</li>
-         <li>TT all methods are called in list context</li>
-         <li><pre>[% author.books<strong>_rs</strong>.count %]</pre> scalar context</li>
-         <li><em>Available for all relationships</em></li>
-      </ul>
+my $rs = $schema-&gt;resultset('CD')-&gt;search({
+    artist_id =&gt; { -in =&gt; $inside_query },
+});</pre>
    </div>
 
    <div class="slide">
-      <h1>Catalyst</h1>
-      <pre>package Your::App::Model::<strong>Foo</strong>;
-use base qw(<strong>Catalyst::Model::Schema::Schema</strong>);
-
-use strict;
-use warnings;
+      <h1><a href="http://search.cpan.org/perldoc?SQL::Abstract#Literal_SQL_with_placeholders_and_bind_values_(subqueries)">Bare SQL w/ Placeholders</a></h1>
+<pre>$rs-&gt;update({
+   # !!! SQL INJECTION VECTOR
+   price =&gt; \"price + $inc",
+});
 
-__PACKAGE__-&gt;config(
-  schema_class =&gt; '<strong>Foo::Schema</strong>',
-);
-
-1;</pre>
-   <p>Keep your Schema in a <em>separate</em> package to your Catalyst application</p>
+$rs-&gt;update({
+   price =&gt; \['price + ?', [inc =&gt; $inc]],
+});
+</pre>
    </div>
 
    <div class="slide">
-      <h1>Catalyst</h1>
-<pre>sub action_name : Local {
-  my ($self, $c) = @_;
-
-  my $model = $c-&gt;model('Schema::Foo');
-  my $author_model = $model-&gt;resultset('Authors');
-
-}
-
-1;</pre>
+      <h1>Questions?</h1>
    </div>
 
+   <div class="slide">
+      <h1>END</h1>
+   </div>
 </div>
 </body>
 </html>