</div>
<div class="slide">
- <h1>books table</h1>
-<pre>CREATE TABLE books(
- id int(8) primary key auto_increment,
- title varchar(255),
- author_id <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>
<li><strong>C</strong> - Create</li>
<h1>SQL: Create</h1>
<pre>my $sth = $dbh->prepare('
INSERT INTO books
- (title, author)
+ (title, author_id)
values (?,?)
');
<div class="slide">
<h1>DBIC: Create</h1>
-<pre>my $book = $book_model->create({
- title => 'A book title',
- author => $author_id,
+<pre>my $book = $book_rs->create({
+ title => 'A book title',
+ author_id => $author_id,
});</pre>
<p>Look ma, no SQL!</p>
</div>
<div class="slide">
<h1>DBIC: Create</h1>
-<pre>my $pratchett = $author_model->create({
+<pre>my $pratchett = $author_rs->create({
name => 'Terry Pratchett',
});</pre>
</div>
<div class="slide">
<h1>DBIC: Read</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>
+ <p>DBIx::Class - TIMTOWTDI</p>
</div>
<div class="slide">
<h1>DBIC: Read</h1>
-<pre>my $book = $book_model->find($book_id);
+<pre>my $book = $book_rs->find($book_id);
-my $book = $book_model->search({
+my $book = $book_rs->search({
title => 'A book title',
}, { rows => 1 })->single;
-my @books = $book_model->search({
+my @books = $book_rs->search({
author => $author_id,
})->all;</pre>
</div>
<div class="slide">
<h1>DBIC: Read</h1>
-<pre>my $books_rs = $book_rs->search({
+<pre>my $resultset = $book_rs->search({
author => $author_id,
});</pre>
<p>Search takes SQL::Abstract formatted queries</p>
</div>
<div class="slide">
- <pre>Example of a DBIC Result</pre>
+<pre>package Foo::Schema::Result::Author;
+__PACKAGE__->table('authors');
+__PACKAGE__->add_columns(
+ id => {
+ data_type => 'int',
+ is_auto_increment => 1
+ },
+ title => {
+ data_type => 'varchar',
+ is_nullable => 1,
+ size => 255,
+ },
+);
+__PACKAGE__->set_primary_key('id');
+__PACKAGE__->has_many( books =>
+ 'Foo::Schema::Result::Book', 'author_id'
+);
+1;
+</pre>
</div>
<div class="slide">
- <pre>Example of a DBIC Result</pre>
+<pre style="float: left; font-size: 80%;">package Foo::Schema::Result::Book;
+use strict; use warnings;
+__PACKAGE__->table('books');
+__PACKAGE__->add_columns(
+ id => {
+ data_type => 'int',
+ is_auto_increment => 1
+ },
+ name => {
+ data_type => 'varchar',
+ is_nullable => 1,
+ size => 255,
+ },
+</pre>
+<pre style="float: left; font-size: 80%;">
+ author_id => {
+ data_type => 'int',
+ size => 8,
+ },
+);
+__PACKAGE__->set_primary_key('id');
+__PACKAGE__->belongs_to( author =>
+ 'Foo::Schema::Result::Author', 'author_id'
+);
+1;
+</pre>
</div>
<div class="slide">
- <p>too much typing! too much maintenance!</p>
+ <h1>->deploy</h1>
+ <p>Perl -> DB</p>
+<pre>my $schema = Foo::Schema->connect($dsn, $user, $pass);
+$schema->deploy
+</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>code for S::L here</pre>
- </div>
+ <p>DB -> Perl</p>
+<pre>package Foo::Schema;
+use strict; use warnings;
+use base 'DBIx::Class::Schema::Loader';
+__PACKAGE__->loader_options({
+ naming => 'v7',
+ debug => $ENV{DBIC_TRACE},
+});
+1;
- <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>
- </div>
+# elsewhere...
- <div class="slide">
- <h1>using your Schema</h1>
- <pre>example usage code goes here</pre>
+my $schema = Foo::Schema->connect($dsn, $user, $pass);
+</pre>
</div>
<div class="slide">
- <h1>DEBUGGING</h1>
- <pre>DBIC_TRACE=1 ./your_script.pl</pre>
+ <h1>Splitting Logic Cleanly</h1>
+ <p>Foo::Schema::Result::Bar = individual row</p>
+ <p>Foo::Schema::ResultSet::Bar = searches / table </p>
</div>
<div class="slide">
- <h1>Schema::Loader</h1>
-<pre>Foo::Schema::Result::Authors->table("authors");
-Foo::Schema::Result::Authors->add_columns(
- id => {
- data_type => "INT",
- default_value => undef,
- is_nullable => 0,
- size => 8
- },
- title => {
- data_type => "VARCHAR",
- default_value => undef,
- is_nullable => 1,
- size => 255,
- },
-);
-Foo::Schema::Result::Authors->set_primary_key("id");</pre>
- </div>
-
- <div class="slide">
- <h1>Schema::Loader</h1>
-<pre>Foo::Schema::Result::Books->table("books");
-Foo::Schema::Result::Books->add_columns(
- id => {
- data_type => "INT",
- default_value => undef,
- is_nullable => 0,
- size => 8
- },
- name => {
- data_type => "VARCHAR",
- default_value => undef,
- is_nullable => 1,
- size => 255,
- },
- author => {
- data_type => "INT",
- default_value => undef,
- is_nullable => 1,
- size => 8
- },
-);
-Foo::Schema::Result::Books->set_primary_key("id");</pre>
+ <h1>Using your Schema</h1>
+<pre>#!perl
+use strict; use warnings;
+use lib 'lib';
+use Foo::Schema;
+my $schema = Foo::Schema->connect($dns, $user, $pass);
+my $author_rs = $schema->resultset('Author');
+my $author = $author_rs->create({
+ name => 'Douglas Adams',
+});
+my $book = $author->add_to_books({
+ title => '42',
+});
+</pre>
</div>
<div class="slide">
- <h1>Schema::Loader</h1>
-<pre>Foo::Schema::Result::Authors->has_many(books => "Foo::Schema::Books",
- { "foreign.author" => "self.id" });
-
-Foo::Schema::Result::Books->belongs_to(author => "Foo::Schema::Authors",
- { id => "author" });</pre>
+ <h1>DEBUGGING</h1>
+ <pre>DBIC_TRACE=1 ./your_script.pl</pre>
</div>
<div class="slide">
<div class="slide">
<h1>overloading</h1>
-<pre>Foo::Schema::Result::Books
-Foo::Schema::ResultSet::Books
-Foo::Schema::Result::Authors
-Foo::Schema::ResultSet::Books</pre>
+<pre>Foo::Schema::Result::Book
+Foo::Schema::ResultSet::Book
+Foo::Schema::Result::Author
+Foo::Schema::ResultSet::Book</pre>
</div>
<div class="slide">
<h1>Result::</h1>
-<pre>package Foo::Schema::Result::Books;
-use base 'DBIx::Class';
+<pre>package Foo::Schema::Result::Book;
+use base 'DBIx::Class::Core';
use strict;
use warnings;
+# Result code here
+
sub isbn {
my $self = shift;
<div class="slide">
<h1>Result:: (inflating)</h1>
-<pre>package Foo::Schema::Result::Books;
-use base 'DBIx::Class';
+<pre>package Foo::Schema::Result::Book;
+use base 'DBIx::Class::Core';
use strict;
use warnings;
+# Result code here
+
+__PACKAGE__->load_components('InflateColumn');
use DateTime::Format::MySQL;
__PACKAGE__-><strong>inflate_column</strong>(
<strong>date_published</strong> => {
inflate => sub { DateTime::Format::MySQL->parse_date(shift) },
deflate => sub { shift->ymd},
- }
-);
-# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
- </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__->inflate_column(
- date_published => {
- <strong>inflate => sub { DateTime::Format::MySQL->parse_date(shift) },
- deflate => sub { shift->ymd},</strong>
- }
+ },
);
-# Automatic see: DBIx::Class::InflateColumn::DateTime
-# Automatic see: DBIx::Class::InflateColumn::DateTime
# Automatic see: DBIx::Class::InflateColumn::DateTime</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 {
- my $self = shift;
- <strong>return $self->search({ title => { -like => '%42%' } })</strong>
-}
-sub by_author {
- my ( $self, $author ) = @_;
- return $self->search({ author => $author->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->search({ title => { -like => '%42%' } });
-}
-sub by_author {
- my ( $self, $author ) = @_;
- <strong>return $self->search({ author => $author->id })</strong>
-}
-
-1;</pre>
- </div>
-
- <div class="slide">
- <h1>ResultSets::</h1>
<pre>use Foo::Schema;
-my $book_model = Foo::Schema->resultset('Books');
-my $book_rs = $book_model->the_ultimate_books;
-my @books = $book_rs->all;</pre>
+my $schema = Foo::Schema->connect(...);
+my $book_rs = Foo::Schema->resultset('Book');
+my $book_search = $book_rs->the_ultimate_books;
+my @books = $book_search->all;</pre>
</div>
<div class="slide">
- <h1>ResultSets::chaining</h1>
-<pre>use Foo::Schema;
-my $book_model = Foo::Schema->resultset('Books');
-my $author_model = Foo::Schema->resultset('Authors');
-my $author = $author_model->search({ name => 'Douglas Adams' })->single;
-my $book_rs = $book_model->the_ultimate_books->by_author($author);
-my @books = $book_rs->all;</pre>
+ <h1>ResultSets: Chaining</h1>
+<pre>
+my $book_rs = $schema->resultset('Book');
+my $author_rs = $schema->resultset('Author');
+my $author = $author_rs->search({ name => 'Douglas Adams' })->single;
+$book_rs = $book_rs->the_ultimate_books->by_author($author);
+my @books = $book_rs->all;</pre>
</div>
<div class="slide">
- <h1>ResultSets::chaining</h1>
-<pre>my $book_rs = $book_model
+ <h1>ResultSets: Chaining</h1>
+<pre>$book_rs = $schema->resultset('Book')
->the_ultimate_books
->by_author($author);</pre>
or
-<pre>my $book_rs = $book_model
- ->the_ultimate_books();
+<pre>my $book_rs = $schema->resultset('Book')
+ ->the_ultimate_books;
$book_rs = $book_rs->by_author($author);</pre>
<pre># Debug (SQL):
</div>
<div class="slide">
- <h1>ResultSets::chaining</h1>
-<pre>my $rs = $book_model
+ <h1>ResultSets: Chaining</h1>
+<pre>my $rs = $book_rs
->category('childrens')
->by_author($author)
->published_after('1812')
<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';
+ <pre>package Foo::Schema::Result::Author;
+use base 'DBIx::Class::Core';
sub new {
my ( $class, $attrs ) = @_;
1;</pre>
<div class="slide">
- <h1>relationships</h1>
+ <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)
+ <h1>Multiple Authors</h1>
+ <p>We want to allow a book to be by more than one author</p>
</div>
<div class="slide">
<h1>a few relationships</h1>
- !
+ <img src="img/afewrels.png" />
</div>
<div class="slide">
- <h1>new join table</h1>
+ <h1>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)
+ book_id int(8),
+ author_id int(8),
+ foreign key (book_id) references books(id),
+ foreign key (author_id) 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>
- </div>
-
- <div class="slide">
- <h1>has_many</h1>
+ALTER TABLE `books` DROP `author_id`;</pre>
</div>
<div class="slide">
<h1>has_many</h1>
-<pre>package Foo::Schema::<strong>Result::Books</strong>;
-
-__PACKAGE__->has_many( author_and_books => "Foo::Schema::Result::AuthorAndBooks",
- { "foreign.book" => "self.id" },
-);
-
-<strong># This is auto generated by Schema::Loader</strong></pre>
+ <img src="img/hasmany1.png" />
</div>
<div class="slide">
<h1>has_many</h1>
-<pre>package Foo::Schema::<strong>Result::Books</strong>;
+<pre>package Foo::Schema::<strong>Result::Book</strong>;
-__PACKAGE__->has_many(
-author_and_books => <strong># name of accessor</strong>
-"Foo::Schema::Result::AuthorAndBooks", <strong># related class</strong>
- { "foreign.book" => "self.id" } <strong># Relationship (magic often works if not
- # specified, but avoid!)</strong>
+__PACKAGE__->has_many( author_and_books =>
+ 'Foo::Schema::Result::Author_Book', 'book_id'
);
-</pre>
</div>
<div class="slide">
<h1>belongs_to</h1>
+ <img src="img/belongsto1.png" />
</div>
<div class="slide">
<h1>belongs_to</h1>
-<pre>package Foo::Schema::<strong>Result::AuthorAndBooks</strong>;
+<pre>package Foo::Schema::<strong>Result::Author_Book</strong>;
__PACKAGE__->belongs_to(
- book => <strong># Accessor name</strong>
- "Foo::Schema::Result::Books", <strong># Related class</strong>
- { id => "book" } <strong># relationship</strong>
+ book =>
+ 'Foo::Schema::Result::Book', 'book_id'
);
</pre>
</div>
<div class="slide">
<h1>same for Authors</h1>
- </div>
-
- <div class="slide">
- <h1>with no coding...</h1>
+ <img src="img/authors.png" />
</div>
<div class="slide">
<h1>many_to_many</h1>
+ <img src="img/m2m.png" />
</div>
<div class="slide">
<h1>many_to_many</h1>
- <pre>package Foo::Schema::<strong>Result::Books</strong>;
-use base 'DBIx::Class';
+ <pre>package Foo::Schema::<strong>Result::Book</strong>;
+use base 'DBIx::Class::Core';
__PACKAGE__->many_to_many(
- authors => "author_and_books", 'author'
+ authors => 'author_and_books', 'author'
);
1;
-
-<strong> # This is <em>NOT</em> auto generated by Schema::Loader </strong></pre>
+</pre>
</div>
<div class="slide">
<h1>many_to_many</h1>
- <pre>package Foo::Schema::<strong>Result::Books</strong>;
-use base 'DBIx::Class';
+ <pre>package Foo::Schema::<strong>Result::Book</strong>;
+use base 'DBIx::Class::Core';
__PACKAGE__->many_to_many(
authors <strong># Accessor name</strong>
<div class="slide">
<h1>many_to_many</h1>
- <pre>package Foo::Schema::Result::Authors;
-use base 'DBIx::Class';
+ <pre>package Foo::Schema::Result::Author;
+use base 'DBIx::Class::Core';
__PACKAGE__->many_to_many(
"books" <strong># Accessor Name</strong>
);
1;
-
-<strong># This is <em>NOT</em> auto generated by Schema::Loader</strong></pre>
+</pre>
</div>
<div class="slide">
- <h1>using many_to_many</h1>
- <pre>#!/usr/bin/perl
-
+ <h1>Using many_to_many</h1>
+ <pre>#!perl
use Foo::Schema;
-
-my $author_model = Foo::Schema->resultset('Authors');
-my $author = $author_model->search({
+my $schema = Foo::Schema->connect(...);
+my $author_rs = $schema->resultset('Authors');
+my $author = $author_rs->search({
name => 'Douglas Adams',
})->single;
$author->add_to_books({
<div class="slide">
<h1>using many_to_many</h1>
- <pre>my $author = $author_model->search({
+ <pre>my $author = $author_rs->search({
name => 'Douglas Adams',
})->single;
<strong>$author->add_to_books({
</div>
<div class="slide">
- <h1>in 16 lines of code</h1>
- </div>
-
- <div class="slide">
<h1>errors</h1>
<p>Read them closely!</p>
</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>
+<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>
</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>
+<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>
</div>
<div class="slide">
</div>
<div class="slide">
+ <h1>LOTS more Features</h1>
+ <ul>
+ <li>FilterColumn</li>
+ <li>Transactions</li>
+ <li>HashRefInflator</li>
+ <li>Subqueries</li>
+ <li>ResultSetColumn</li>
+ <li>Aggregate Queries</li>
+ </ul>
+ </div>
+
+ <div class="slide">
<h1>bonus slides!</h1>
</div>
);
1;</pre>
- <p>Keep your Schema in a <em>separate</em> package to your Catalyst application</p>
+ <p>Keep your Schema in a <em>separate</em> package from your Catalyst application</p>
</div>
<div class="slide">
<pre>sub action_name : Local {
my ($self, $c) = @_;
- my $model = $c->model('Schema::Foo');
- my $author_model = $model->resultset('Authors');
+ my $schema = $c->model('Schema::Foo');
+ my $author_rs = $schema->resultset('Authors');
}