236
Introduction to Jifty Sterling Hanenkamp, PPW 2008

Introduction to Jifty

Embed Size (px)

DESCRIPTION

A brief introduction to Jifty using a demo app that emulates Qublog

Citation preview

Page 1: Introduction to Jifty

Introduction to Jifty

Sterling Hanenkamp, PPW 2008

Page 2: Introduction to Jifty

I Work for a Living

Page 3: Introduction to Jifty

I Work for a Living

• Contract work / Billable Hours: How do I track them?

Page 4: Introduction to Jifty

I Work for a Living

• Contract work / Billable Hours: How do I track them?

• Weekly Status Reports: What did I do?

Page 5: Introduction to Jifty

I Work for a Living

• Contract work / Billable Hours: How do I track them?

• Weekly Status Reports: What did I do?

• Reliable Memory: Did I do that? How? When? Why?

Page 6: Introduction to Jifty

I Work for a Living

• Contract work / Billable Hours: How do I track them?

• Weekly Status Reports: What did I do?

• Reliable Memory: Did I do that? How? When? Why?

• Task Lists: What should I do next?

Page 7: Introduction to Jifty

Existing Solutions

Time Sheet

Page 8: Introduction to Jifty

Existing Solutions

Planner

Page 9: Introduction to Jifty

Existing Solutions

Scratch Paper

Page 10: Introduction to Jifty

Existing Solutions

Page 11: Introduction to Jifty

Existing Solutions

Hiveminder

Stikkit

Day Planner

iCal/Apple Mail

Sunbird

Lightning

Entourage

Things

OmniFocus

Page 12: Introduction to Jifty

Qublog

Page 13: Introduction to Jifty

• I don’t want to store this information in four places

Qublog

Page 14: Introduction to Jifty

• I don’t want to store this information in four places

• I have a habit of writing down what I’m doing to focus

Qublog

Page 15: Introduction to Jifty

• I don’t want to store this information in four places

• I have a habit of writing down what I’m doing to focus

• I needed something else to do with my lack of spare time

Qublog

Page 16: Introduction to Jifty

• I don’t want to store this information in four places

• I have a habit of writing down what I’m doing to focus

• I needed something else to do with my lack of spare time

• I built Qublog (originally MyToDo and Kiln for a short while)

Qublog

Page 17: Introduction to Jifty

• I don’t want to store this information in four places

• I have a habit of writing down what I’m doing to focus

• I needed something else to do with my lack of spare time

• I built Qublog (originally MyToDo and Kiln for a short while)

• It’s written using Jifty

Qublog

Page 18: Introduction to Jifty

• I don’t want to store this information in four places

• I have a habit of writing down what I’m doing to focus

• I needed something else to do with my lack of spare time

• I built Qublog (originally MyToDo and Kiln for a short while)

• It’s written using Jifty

• We’re going to look at how I did it to explain Jifty

Qublog

Page 19: Introduction to Jifty

What’s it look like?

Page 20: Introduction to Jifty

What’s it look like?

Page 21: Introduction to Jifty

What’s it look like?

Page 22: Introduction to Jifty

What’s it look like?

Page 23: Introduction to Jifty

What’s it look like?

Page 24: Introduction to Jifty

What’s it look like?

Page 25: Introduction to Jifty

What’s it look like?

Page 26: Introduction to Jifty

What’s it look like?

Page 27: Introduction to Jifty

What’s it look like?

Page 28: Introduction to Jifty

What’s it look like?

Page 29: Introduction to Jifty

What’s it look like?

Page 30: Introduction to Jifty

What’s it look like?

Page 31: Introduction to Jifty

What’s it look like?

Page 32: Introduction to Jifty

What’s it look like?

Page 33: Introduction to Jifty

What’s it look like?

Page 34: Introduction to Jifty

Qublog

Page 35: Introduction to Jifty

Qublog

• Provides a Journal for keeping thoughts

Page 36: Introduction to Jifty

Qublog

• Provides a Journal for keeping thoughts

• Provides a To Do List for organizing tasks

Page 37: Introduction to Jifty

Qublog

• Provides a Journal for keeping thoughts

• Provides a To Do List for organizing tasks

• Journal Comments are grouped into Timers that keep track of time spent

Page 38: Introduction to Jifty

Qublog

• Provides a Journal for keeping thoughts

• Provides a To Do List for organizing tasks

• Journal Comments are grouped into Timers that keep track of time spent

• Timers are grouped into Entries to sum up work for reporting

Page 39: Introduction to Jifty

Qublog

• Provides a Journal for keeping thoughts

• Provides a To Do List for organizing tasks

• Journal Comments are grouped into Timers that keep track of time spent

• Timers are grouped into Entries to sum up work for reporting

• Comments also connect with Tasks to keep track of what’s next

Page 40: Introduction to Jifty

This is a talk about Jifty

Page 41: Introduction to Jifty

This is a talk about Jifty

• Not Qublog

• Okay, so let’s see if we can build QublogMini in the time remaining...

Page 42: Introduction to Jifty

Install Jifty

As with “that-other-framework,” the worst part is over when you

finish the install.

Page 43: Introduction to Jifty

Install Jifty

Page 44: Introduction to Jifty

• Method 1: Shipwright

Install Jifty

Page 45: Introduction to Jifty

• Method 1: Shipwright

svn co http://code.bestpractical.com/shipwright/jifty/ jifty-buildercd jifty-builder./bin/shipwright-builder # optionally --skip perl --skip-testcp -rvp /tmp/jifty-$random/jifty /usr/local/jiftyln -s /usr/local/jifty/bin/jifty /usr/local/bin/jifty

Install Jifty

Page 46: Introduction to Jifty

• Method 1: Shipwright

svn co http://code.bestpractical.com/shipwright/jifty/ jifty-buildercd jifty-builder./bin/shipwright-builder # optionally --skip perl --skip-testcp -rvp /tmp/jifty-$random/jifty /usr/local/jiftyln -s /usr/local/jifty/bin/jifty /usr/local/bin/jifty

• Method 2: CPAN

Install Jifty

Page 47: Introduction to Jifty

• Method 1: Shipwright

svn co http://code.bestpractical.com/shipwright/jifty/ jifty-buildercd jifty-builder./bin/shipwright-builder # optionally --skip perl --skip-testcp -rvp /tmp/jifty-$random/jifty /usr/local/jiftyln -s /usr/local/jifty/bin/jifty /usr/local/bin/jifty

• Method 2: CPAN

perl -MCPAN -eshell # or just cpancpan> notest install Jifty

Install Jifty

Page 48: Introduction to Jifty

• Method 1: Shipwright

svn co http://code.bestpractical.com/shipwright/jifty/ jifty-buildercd jifty-builder./bin/shipwright-builder # optionally --skip perl --skip-testcp -rvp /tmp/jifty-$random/jifty /usr/local/jiftyln -s /usr/local/jifty/bin/jifty /usr/local/bin/jifty

• Method 2: CPAN

perl -MCPAN -eshell # or just cpancpan> notest install Jifty

Install Jifty

“notest” saves ~60 minutes according to Audrey

Page 49: Introduction to Jifty

• Method 1: Shipwright

svn co http://code.bestpractical.com/shipwright/jifty/ jifty-buildercd jifty-builder./bin/shipwright-builder # optionally --skip perl --skip-testcp -rvp /tmp/jifty-$random/jifty /usr/local/jiftyln -s /usr/local/jifty/bin/jifty /usr/local/bin/jifty

• Method 2: CPAN

perl -MCPAN -eshell # or just cpancpan> notest install Jifty

Install Jifty

“notest” saves ~60 minutes according to Audrey

“notest” will get you no support according to Jesse

Page 50: Introduction to Jifty

• Method 1: Shipwright

svn co http://code.bestpractical.com/shipwright/jifty/ jifty-buildercd jifty-builder./bin/shipwright-builder # optionally --skip perl --skip-testcp -rvp /tmp/jifty-$random/jifty /usr/local/jiftyln -s /usr/local/jifty/bin/jifty /usr/local/bin/jifty

• Method 2: CPAN

perl -MCPAN -eshell # or just cpancpan> notest install Jifty

Install Jifty

Page 51: Introduction to Jifty

• Method 1: Shipwright

svn co http://code.bestpractical.com/shipwright/jifty/ jifty-buildercd jifty-builder./bin/shipwright-builder # optionally --skip perl --skip-testcp -rvp /tmp/jifty-$random/jifty /usr/local/jiftyln -s /usr/local/jifty/bin/jifty /usr/local/bin/jifty

• Method 2: CPAN

perl -MCPAN -eshell # or just cpancpan> notest install Jifty

• ActiveState installation on Windows: http://jifty.org/view/DownloadJifty

Install Jifty

Page 52: Introduction to Jifty

• Method 1: Shipwright

svn co http://code.bestpractical.com/shipwright/jifty/ jifty-buildercd jifty-builder./bin/shipwright-builder # optionally --skip perl --skip-testcp -rvp /tmp/jifty-$random/jifty /usr/local/jiftyln -s /usr/local/jifty/bin/jifty /usr/local/bin/jifty

• Method 2: CPAN

perl -MCPAN -eshell # or just cpancpan> notest install Jifty

• ActiveState installation on Windows: http://jifty.org/view/DownloadJifty

• Jifty is in Debian unstable

Install Jifty

Page 53: Introduction to Jifty

% jifty app --name QublogMini

Page 54: Introduction to Jifty

% jifty app --name QublogMiniCreating new application QublogMiniCreating directory QublogMini/libCreating directory QublogMini/lib/QublogMiniCreating directory QublogMini/binCreating directory QublogMini/etcCreating directory QublogMini/docCreating directory QublogMini/logCreating directory QublogMini/varCreating directory QublogMini/var/masonCreating directory QublogMini/shareCreating directory QublogMini/share/poCreating directory QublogMini/share/webCreating directory QublogMini/share/web/templatesCreating directory QublogMini/share/web/staticCreating directory QublogMini/lib/QublogMini/ModelCreating directory QublogMini/lib/QublogMini/ActionCreating directory QublogMini/tCreating configuration file QublogMini/etc/config.yml

Page 55: Introduction to Jifty

% cd QublogMini% find . -type f

Page 56: Introduction to Jifty

% cd QublogMini% find . -type f./bin/jifty./etc/config.yml./Makefile.PL

Page 57: Introduction to Jifty
Page 58: Introduction to Jifty

% ./bin/jifty server

Page 59: Introduction to Jifty

WARN - Application schema has no version in the database.WARN - Automatically creating your database.INFO - Generating SQL for application QublogMini...INFO - Using Jifty::Model::Session, as it appears to be new.INFO - Using Jifty::Model::Metadata, as it appears to be new.INFO - Set up version v0.0.1, jifty version 0.804080INFO - You can connect to your server at http://localhost:8888/

% ./bin/jifty server

Page 60: Introduction to Jifty

WARN - Application schema has no version in the database.WARN - Automatically creating your database.INFO - Generating SQL for application QublogMini...INFO - Using Jifty::Model::Session, as it appears to be new.INFO - Using Jifty::Model::Metadata, as it appears to be new.INFO - Set up version v0.0.1, jifty version 0.804080INFO - You can connect to your server at http://localhost:8888/

% ./bin/jifty server

Page 61: Introduction to Jifty

Take a Look

Page 62: Introduction to Jifty

OMG! Ponies!!!

Page 63: Introduction to Jifty

Not a very interesting journaling app... let’s fix it.

Page 64: Introduction to Jifty

% ./bin/jifty model --name Comment

Page 65: Introduction to Jifty

% ./bin/jifty model --name CommentWriting file t/00-model-Comment.tWriting file lib/QublogMini/Model/Comment.pm

Page 66: Introduction to Jifty

% ./bin/jifty model --name CommentWriting file t/00-model-Comment.tWriting file lib/QublogMini/Model/Comment.pm

% vim lib/QublogMini/Model/Comment.pm

Page 67: Introduction to Jifty

package QublogMini::Model::Comment;use Jifty::DBI::Schema;

use QublogMini::Record schema {

};

Page 68: Introduction to Jifty

package QublogMini::Model::Comment;use Jifty::DBI::Schema;

use QublogMini::Record schema { column commented_on => type is 'datetime', label is 'Commented on', filters are qw( Jifty::DBI::Filter::DateTime );

column name => type is 'text', label is 'Name', render as 'textarea';};

Page 69: Introduction to Jifty

% bin/jifty server

Page 70: Introduction to Jifty

% bin/jifty server WARN - Application schema has no version in the database.WARN - Automatically creating your database.INFO - Generating SQL for application QublogMini...INFO - Using QublogMini::Model::Comment, as it appears to be new.INFO - Using Jifty::Model::Session, as it appears to be new.INFO - Using Jifty::Model::Metadata, as it appears to be new.INFO - Set up version v0.0.1, jifty version 0.804080INFO - You can connect to your server at http://localhost:8888/

Page 71: Introduction to Jifty
Page 72: Introduction to Jifty
Page 73: Introduction to Jifty
Page 74: Introduction to Jifty
Page 75: Introduction to Jifty
Page 76: Introduction to Jifty
Page 77: Introduction to Jifty
Page 78: Introduction to Jifty
Page 79: Introduction to Jifty
Page 80: Introduction to Jifty

% bin/jifty model --name Timer

Page 81: Introduction to Jifty

% bin/jifty model --name TimerWriting file lib/QublogMini/Model/Timer.pmWriting file t/00-model-Timer.t

Page 82: Introduction to Jifty

% bin/jifty model --name TimerWriting file lib/QublogMini/Model/Timer.pmWriting file t/00-model-Timer.t

% vim lib/QublogMini/Model/Timer.pm

Page 83: Introduction to Jifty

package QublogMini::Model::Timer;use Jifty::DBI::Schema;

use QublogMini::Record schema {

};

Page 84: Introduction to Jifty

package QublogMini::Model::Timer; use Jifty::DBI::Schema;

use QublogMini::Record schema { column started_on => label is 'Started on', filters are qw( Jifty::DBI::Filter::DateTime );

column stopped_on => label is 'Stopped on', filters are qw( Jifty::DBI::Filter::DateTime );

column comments => references QublogMini::Model::CommentCollection by 'timer';

};

sub since { '0.0.2' }

Page 85: Introduction to Jifty

package QublogMini::Model::Comment;use Jifty::DBI::Schema;

use QublogMini::Record schema { column commented_on => type is 'datetime', label is 'Commented on', filters are qw( Jifty::DBI::Filter::DateTime ), ;

column name => type is 'text', label is 'Name', render as 'textarea', ;

};

Page 86: Introduction to Jifty

package QublogMini::Model::Comment;use Jifty::DBI::Schema;

use QublogMini::Record schema { column commented_on => type is 'datetime', label is 'Commented on', filters are qw( Jifty::DBI::Filter::DateTime ), ;

column name => type is 'text', label is 'Name', render as 'textarea', ;

column timer => label is 'Timer', since '0.0.2', references QublogMini::Model::Timer;};

Page 87: Introduction to Jifty

% bin/jifty server

Page 88: Introduction to Jifty

% bin/jifty server WARN - Application schema version in database (v0.0.1) doesn't match application schema version (0.0.2)WARN - Automatically upgrading your database to match the current application schema.Jifty version 0.809130 up to date.Jifty::Plugin::LetMe version v0.0.1 up to date.Jifty::Plugin::SkeletonApp version v0.0.1 up to date.Jifty::Plugin::REST version v0.0.1 up to date.Jifty::Plugin::Halo version v0.0.1 up to date.Jifty::Plugin::ErrorTemplates version v0.0.1 up to date.Jifty::Plugin::OnlineDocs version v0.0.1 up to date.Jifty::Plugin::CompressedCSSandJS version v0.0.1 up to date.Jifty::Plugin::AdminUI version v0.0.1 up to date.INFO - Generating SQL to upgrade QublogMini v0.0.1 database to v0.0.2INFO - Upgrading through 0.0.2INFO - Running upgrade scriptINFO - Upgraded to version v0.0.2INFO - You can connect to your server at http://localhost:8888/

Page 89: Introduction to Jifty
Page 90: Introduction to Jifty
Page 91: Introduction to Jifty
Page 92: Introduction to Jifty
Page 93: Introduction to Jifty
Page 94: Introduction to Jifty
Page 95: Introduction to Jifty

package QublogMini::Model::Timer;

# ...

sub name { my $self = shift; $self->started_on . ' to ' . $self->stopped_on}

Page 96: Introduction to Jifty

% bin/jifty model --name Entry

Page 97: Introduction to Jifty

% bin/jifty model --name EntryWriting file t/00-model-Entry.tWriting file lib/QublogMini/Model/Entry.pm

Page 98: Introduction to Jifty

% bin/jifty model --name EntryWriting file t/00-model-Entry.tWriting file lib/QublogMini/Model/Entry.pm

% vim lib/QublogMini/Model/Entry.pm

Page 99: Introduction to Jifty

package QublogMini::Model::Entry;use Jifty::DBI::Schema;

use QublogMini::Record schema {

};

Page 100: Introduction to Jifty

package QublogMini::Model::Entry; use Jifty::DBI::Schema;

use QublogMini::Record schema { column name => type is 'text', label is 'Name', is mandatory;

column url => type is 'text', label is 'Name';

column timers => references QublogMini::Model::TimerCollection by 'entry';};

sub since { '0.0.3' }

Page 101: Introduction to Jifty

package QublogMini::Model::Timer;use Jifty::DBI::Schema;

use QublogMini::Record schema { # ...

column entry => label is 'Entry', since '0.0.3', references QublogMini::Model::Entry;

# ...};

sub name { my $self = shift; my $name = ''; $name .= $self->entry->name . ': ' if $self->entry->id; $name .= $self->started_on . ' to ' . $self->stopped_on return $name;}

Page 102: Introduction to Jifty

--- framework: AdminMode: 1 ApplicationClass: QublogMini ApplicationName: QublogMini ApplicationUUID: 1198420A-95A9-11DD-8ED4-3E4643B9151E ConfigFileVersion: 4 Database: AutoUpgrade: 1 CheckSchema: 1 Database: qublogmini Driver: SQLite Host: localhost Password: '' RecordBaseClass: Jifty::DBI::Record::Cachable User: '' Version: 0.0.2

Page 103: Introduction to Jifty

--- framework: AdminMode: 1 ApplicationClass: QublogMini ApplicationName: QublogMini ApplicationUUID: 1198420A-95A9-11DD-8ED4-3E4643B9151E ConfigFileVersion: 4 Database: AutoUpgrade: 1 CheckSchema: 1 Database: qublogmini Driver: SQLite Host: localhost Password: '' RecordBaseClass: Jifty::DBI::Record::Cachable User: '' Version: 0.0.2

Page 104: Introduction to Jifty

--- framework: AdminMode: 1 ApplicationClass: QublogMini ApplicationName: QublogMini ApplicationUUID: 1198420A-95A9-11DD-8ED4-3E4643B9151E ConfigFileVersion: 4 Database: AutoUpgrade: 1 CheckSchema: 1 Database: qublogmini Driver: SQLite Host: localhost Password: '' RecordBaseClass: Jifty::DBI::Record::Cachable User: '' Version: 0.0.3

Page 105: Introduction to Jifty

% bin/jifty server

Page 106: Introduction to Jifty

% bin/jifty server WARN - Application schema version in database (v0.0.2) doesn't match application schema version (0.0.3)WARN - Automatically upgrading your database to match the current application schema.Jifty version 0.809130 up to date.Jifty::Plugin::LetMe version v0.0.1 up to date.Jifty::Plugin::SkeletonApp version v0.0.1 up to date.Jifty::Plugin::REST version v0.0.1 up to date.Jifty::Plugin::Halo version v0.0.1 up to date.Jifty::Plugin::ErrorTemplates version v0.0.1 up to date.Jifty::Plugin::OnlineDocs version v0.0.1 up to date.Jifty::Plugin::CompressedCSSandJS version v0.0.1 up to date.Jifty::Plugin::AdminUI version v0.0.1 up to date.INFO - Generating SQL to upgrade QublogMini v0.0.2 database to v0.0.3INFO - Upgrading through 0.0.3INFO - Running upgrade scriptINFO - Upgraded to version v0.0.3INFO - You can connect to your server at http://localhost:8888/

Page 107: Introduction to Jifty
Page 108: Introduction to Jifty

Ponies are great!

Page 109: Introduction to Jifty

Ponies are great!

But where’s the UI?

Page 110: Introduction to Jifty

# Dispatcher maps URLs to Views% vim lib/QublogMini/Dispatcher.pm

Page 111: Introduction to Jifty

package QublogMini::Dispatcher;use Jifty::Dispatcher -base;

Page 112: Introduction to Jifty

package QublogMini::Dispatcher;use Jifty::Dispatcher -base;

on '/' => dispatch '/today';

Page 113: Introduction to Jifty

package QublogMini::Dispatcher;use Jifty::Dispatcher -base;

on '/' => dispatch '/today';on '/today' => run { my $entries = QublogMini::Model::EntryCollection->new; my $timer_alias = $entries->join( column1 => 'id', table2 => QublogMini::Model::Timer->table, column2 => 'entry', ); $entries->limit( alias => $timer_alias, column => 'started_on', operator => '>=', value => DateTime->today, entry_aggregator => 'AND', ); $entries->limit( alias => $timer_alias, column => 'started_on', operator => '<', value => DateTime->today->add( days => 1 ), entry_aggregator => 'AND', ); set entries => $entries; show '/today';};

Page 114: Introduction to Jifty

package QublogMini::View;use Jifty::View::Declare -base;

template '/today' => page { { title is "Today's Journal" }

my $entries = get 'entries'; while (my $entry = $entries->next) { h2 { $entry->name };

p { hyperlink label => $entry->url, url => $entry->url }; }};

Page 115: Introduction to Jifty
Page 116: Introduction to Jifty

template '/today' => page { { title is "Today's Journal" }

my $entries = get 'entries'; while (my $entry = $entries->next) { h2 { $entry->name };

p { hyperlink label => $entry->url, url => $entry->url };

show '/timers', $entry; }};

Page 117: Introduction to Jifty

private template '/timers' => sub { my ($self, $entry) = @_;

my $timers = $entry->timers; while (my $timer = $timers->next) { show '/show_comment', $timer->stopped_on, _('Stopped timer.') if $timer->stopped_on; show '/comments', $timer; show '/show_comment', $timer->started_on, _('Started timer.'); }};

Page 118: Introduction to Jifty

private template '/comments' => sub { my ($self, $timer) = @_;

my $comments = $timer->comments;

while (my $comment = $comments->next) { show '/show_comment', $comment->commented_on, $comment->name; }};

private template '/show_comment' => sub { my ($self, $time, $message) = @_; p { { class is 'time' } $time }; p { { class is 'comment' } $message };};

Page 119: Introduction to Jifty
Page 120: Introduction to Jifty

Fine. We already knew that. Where’s the

“interface”?

Page 121: Introduction to Jifty

template '/today' => page { { title is "Today's Journal" }

form { render_region name => 'add_entry', path => '/add_entry_button', ; };

my $entries = get 'entries'; while (my $entry = $entries->next) { h2 { $entry->name };

p { hyperlink label => $entry->url, url => $entry->url; };

show '/timers', $entry; }};

Page 122: Introduction to Jifty

template '/add_entry_button' => sub { form_submit label => _('Add Entry'), onclick => { region => Jifty->web->current_region, replace_with => '/add_entry_form', }, ;};

Page 123: Introduction to Jifty

template '/add_entry_form' => sub { my $entry_action = new_action class => 'CreateEntry'; render_action $entry_action, [ qw( name url ) ]; form_submit label => _('Add Entry'), onclick => { submit => $entry_action, region => Jifty->web->current_region, replace_with => '/add_entry_button', }, ;};

Page 124: Introduction to Jifty
Page 125: Introduction to Jifty
Page 126: Introduction to Jifty
Page 127: Introduction to Jifty
Page 128: Introduction to Jifty
Page 129: Introduction to Jifty

Where’d it go?

Page 130: Introduction to Jifty

Where’d it go?

2 Problems

Page 131: Introduction to Jifty

Where’d it go?

2 ProblemsWe need a timer

too.

Page 132: Introduction to Jifty

Where’d it go?

2 ProblemsWe need a timer

too.We need to

redraw the journal.

Page 133: Introduction to Jifty

package QublogMini::Model::Entry;use Jifty::DBI::Schema;

use DateTime;

# ...

# Add a timer when we add an entrysub after_create { my ($self, $id) = @_; return unless $$id;

my $timer = QublogMini::Model::Timer->new; $timer->create( entry => $$id, started_on => DateTime->now, );

return 1;}

Page 134: Introduction to Jifty

template '/today' => page { { title is "Today's Journal" }

my $entries = get 'entries'; while (my $entry = $entries->next) { h2 { $entry->name };

p { hyperlink label => $entry->url, url => $entry->url };

show '/timers', $entry; }};

Page 135: Introduction to Jifty

template '/today' => page { { title is "Today's Journal" }

my $entries = get 'entries'; while (my $entry = $entries->next) { h2 { $entry->name };

p { hyperlink label => $entry->url, url => $entry->url };

show '/timers', $entry; }};

Page 136: Introduction to Jifty

# Replace /today with a regiontemplate '/today' => page { { title is "Today's Journal" }

render_region name => 'entries', path => '/entries', ;};

Page 137: Introduction to Jifty

# Replace /today with a regiontemplate '/today' => page { { title is "Today's Journal" }

render_region name => 'entries', path => '/entries', ;};

Page 138: Introduction to Jifty

# Add a new entries fragmenttemplate '/entries' => sub { form { render_region name => 'add_entry', path => '/add_entry_button', ; };

my $entries = get 'entries'; while (my $entry = $entries->next) { h2 { $entry->name };

p { hyperlink label => $entry->url, url => $entry->url; };

show '/timers', $entry; }};

Page 139: Introduction to Jifty

on '/today' => run { my $entries = QublogMini::Model::EntryCollection->new; my $timer_alias = $entries->join( column1 => 'id', table2 => QublogMini::Model::Timer->table, column2 => 'entry', ); $entries->limit( alias => $timer_alias, column => 'started_on', operator => '>=', value => DateTime->today, entry_aggregator => 'AND', ); $entries->limit( alias => $timer_alias, column => 'started_on', operator => '<', value => DateTime->today->add( days => 1 ), entry_aggregator => 'AND', ); set entries => $entries;};

Page 140: Introduction to Jifty

on '/today' => run { my $entries = QublogMini::Model::EntryCollection->new; my $timer_alias = $entries->join( column1 => 'id', table2 => QublogMini::Model::Timer->table, column2 => 'entry', ); $entries->limit( alias => $timer_alias, column => 'started_on', operator => '>=', value => DateTime->today, entry_aggregator => 'AND', ); $entries->limit( alias => $timer_alias, column => 'started_on', operator => '<', value => DateTime->today->add( days => 1 ), entry_aggregator => 'AND', ); set entries => $entries;};

Page 141: Introduction to Jifty

on '/entries' => run { my $entries = QublogMini::Model::EntryCollection->new; my $timer_alias = $entries->join( column1 => 'id', table2 => QublogMini::Model::Timer->table, column2 => 'entry', ); $entries->limit( alias => $timer_alias, column => 'started_on', operator => '>=', value => DateTime->today, entry_aggregator => 'AND', ); $entries->limit( alias => $timer_alias, column => 'started_on', operator => '<', value => DateTime->today->add( days => 1 ), entry_aggregator => 'AND', ); set entries => $entries;};

Page 142: Introduction to Jifty

template '/add_entry_form' => sub { my $entry_action = new_action class => 'CreateEntry'; render_action $entry_action, [ qw( name url ) ]; form_submit label => _('Add Entry'), onclick => { submit => $entry_action, region => Jifty->web->current_region, replace_with => '/add_entry_button', }, ;};

Page 143: Introduction to Jifty

template '/add_entry_form' => sub { my $entry_action = new_action class => 'CreateEntry'; render_action $entry_action, [ qw( name url ) ]; form_submit label => _('Add Entry'), onclick => { submit => $entry_action, region => Jifty->web->current_region, replace_with => '/add_entry_button', }, ;};

Page 144: Introduction to Jifty

# Make our entry form update everything properlytemplate '/add_entry_form' => sub { my $entry_action = new_action class => 'CreateEntry'; render_action $entry_action, [ qw( name url ) ]; form_submit label => _('Add Entry'), onclick => [ { submit => $entry_action, }, { region => Jifty->web->current_region, replace_with => '/add_entry_button', }, { refresh => Jifty->web->current_region->parent, }, ], ;};

Page 145: Introduction to Jifty

# Make our entry form update everything properlytemplate '/add_entry_form' => sub { my $entry_action = new_action class => 'CreateEntry'; render_action $entry_action, [ qw( name url ) ]; form_submit label => _('Add Entry'), onclick => [ { submit => $entry_action, }, { region => Jifty->web->current_region, replace_with => '/add_entry_button', }, { refresh => Jifty->web->current_region->parent, }, ], ;};

Page 146: Introduction to Jifty
Page 147: Introduction to Jifty
Page 148: Introduction to Jifty
Page 149: Introduction to Jifty
Page 150: Introduction to Jifty
Page 151: Introduction to Jifty

Bummer.Wrong Order.

Page 152: Introduction to Jifty

Bummer.Wrong Order.

Page 153: Introduction to Jifty

on '/entries' => run { my $entries = QublogMini::Model::EntryCollection->new; my $timer_alias = $entries->join( column1 => 'id', table2 => QublogMini::Model::Timer->table, column2 => 'entry', );

# ...

$entries->order_by({ alias => $timer_alias, column => 'started_on', order => 'DES', }); set entries => $entries;};

Page 154: Introduction to Jifty

on '/entries' => run { my $entries = QublogMini::Model::EntryCollection->new; my $timer_alias = $entries->join( column1 => 'id', table2 => QublogMini::Model::Timer->table, column2 => 'entry', );

# ...

$entries->order_by({ alias => $timer_alias, column => 'started_on', order => 'DES', }); set entries => $entries;};

Page 155: Introduction to Jifty
Page 156: Introduction to Jifty

We have entries and timers, but what about comments?

Page 157: Introduction to Jifty

package QublogMini::Model::Comment;use Jifty::DBI::Schema;

use DateTime;

# ...

sub before_create { my ($self, $args) = @_;

$args->{commented_on} = DateTime->now;

return 1;}

Page 158: Introduction to Jifty

template '/add_entry_button' => sub { form_submit label => _('Add Entry'), onclick => { region => Jifty->web->current_region, replace_with => '/add_entry_form', }, ; form_submit label => _('Add Comment'), onclick => { region => Jifty->web->current_region, replace_with => '/add_comment_form', }, ;};

Page 159: Introduction to Jifty

template '/add_entry_button' => sub { form_submit label => _('Add Entry'), onclick => { region => Jifty->web->current_region, replace_with => '/add_entry_form', }, ; form_submit label => _('Add Comment'), onclick => { region => Jifty->web->current_region, replace_with => '/add_comment_form', }, ;};

Page 160: Introduction to Jifty

template '/add_comment_form' => sub { my $timer = QublogMini::Model::Timer->new; $timer->load_current; # loads the latest running timer my $comment_action = new_action class => 'CreateComment'; render_action $comment_action, [ qw( name ) ]; form_submit label => _('Add Comment'), onclick => [ { submit => { action => $comment_action, arguments => { timer => $timer->id, }, }, }, { region => Jifty->web->current_region, replace_with => '/add_entry_button', }, { refresh => Jifty->web->current_region->parent, }, ], ; # ...

Page 161: Introduction to Jifty

# ...

form_submit label => _('Cancel'), onclick => { region => Jifty->web->current_region, replace_with => '/add_entry_button', }, ;};

Page 162: Introduction to Jifty
Page 163: Introduction to Jifty
Page 164: Introduction to Jifty
Page 165: Introduction to Jifty
Page 166: Introduction to Jifty
Page 167: Introduction to Jifty
Page 168: Introduction to Jifty
Page 169: Introduction to Jifty
Page 170: Introduction to Jifty
Page 171: Introduction to Jifty

What about Validation

Page 172: Introduction to Jifty

What about Validation

• Easy

Page 173: Introduction to Jifty

What about Validation

• Easy

• Add a validate_XXX method to the model

Page 174: Introduction to Jifty

What about Validation

• Easy

• Add a validate_XXX method to the model

• Let’s try it

Page 175: Introduction to Jifty

sub validate_url { my ($self, $url) = @_;

if ($url !~ m[^https?://]) { return (0, 'That does not look like a URL.'); }

return 1;}

Page 176: Introduction to Jifty
Page 177: Introduction to Jifty
Page 178: Introduction to Jifty

Canonicalization

Page 179: Introduction to Jifty

Canonicalization

• You can also canonicalize something

Page 180: Introduction to Jifty

Canonicalization

• You can also canonicalize something

• What the heck is that?

Page 181: Introduction to Jifty

Canonicalization

• You can also canonicalize something

• What the heck is that?

• Rather than slap their hand, fix it for them

Page 182: Introduction to Jifty

Canonicalization

• You can also canonicalize something

• What the heck is that?

• Rather than slap their hand, fix it for them

• For example, we could... (but won’t)...

Page 183: Introduction to Jifty

sub canonicalize_url { my ($self, $url) = @_;

if ($url !~ m[^https?://]) { return 'http://'.$url; }

return $url;}

Page 184: Introduction to Jifty

sub canonicalize_url { my ($self, $url) = @_;

if ($url !~ m[^https?://]) { return 'http://'.$url; }

return $url;}

Too naïve, I refuse to implement it!

Page 185: Introduction to Jifty

sub canonicalize_url { my ($self, $url) = @_;

if ($url !~ m[^https?://]) { return 'http://'.$url; }

return $url;}

Too naïve, I refuse to implement it!

But it was the best I could come up with on

short notice.

Page 186: Introduction to Jifty

Halos

Page 187: Introduction to Jifty

Halos

Page 188: Introduction to Jifty

Halos

Page 189: Introduction to Jifty

Halos

I’m the view code for this “frame” in the

page!

Page 190: Introduction to Jifty

Halos

Page 191: Introduction to Jifty

Halos

Page 192: Introduction to Jifty

Halos

Page 193: Introduction to Jifty

Halos

View the HTML source, Luke.

Page 194: Introduction to Jifty

Halos

Page 195: Introduction to Jifty

Halos

Page 196: Introduction to Jifty

Halos

Page 197: Introduction to Jifty

Page Info

Page 198: Introduction to Jifty

Page Info

Page 199: Introduction to Jifty

Page Info

Page 200: Introduction to Jifty

Page Info

Page 201: Introduction to Jifty

Page Info

Page 202: Introduction to Jifty

Page Info

Page 203: Introduction to Jifty

Page Info

• Click on things to view info

Page 204: Introduction to Jifty

Page Info

• Click on things to view info

• SQL Logging

Page 205: Introduction to Jifty

Page Info

• Click on things to view info

• SQL Logging

• SQL Profiling

Page 206: Introduction to Jifty

Page Info

• Click on things to view info

• SQL Logging

• SQL Profiling

• Template Profiling

Page 207: Introduction to Jifty

Developer Mode

Page 208: Introduction to Jifty

Developer Mode

• Module::Refresh

Page 209: Introduction to Jifty

Developer Mode

• Module::Refresh

• Tracing with Log4Perl

Page 210: Introduction to Jifty

Developer Mode

• Module::Refresh

• Tracing with Log4Perl

• Administration Console

Page 211: Introduction to Jifty

Developer Mode

• Module::Refresh

• Tracing with Log4Perl

• Administration Console

• (actually, that’s Administrator Mode)

Page 212: Introduction to Jifty

Deployment

Page 213: Introduction to Jifty

Deployment

• Choice of web servers: FastCGI on Apache / Lighttpd, HTTP::Server::Simple, mod_perl support (a little weak at the moment)

Page 214: Introduction to Jifty

Deployment

• Choice of web servers: FastCGI on Apache / Lighttpd, HTTP::Server::Simple, mod_perl support (a little weak at the moment)

• Choice of DB servers: SQLite (great for getting started/testing, but production is possible), PostgreSQL, MySQL, and other servers supported

Page 215: Introduction to Jifty

Deployment

• Choice of web servers: FastCGI on Apache / Lighttpd, HTTP::Server::Simple, mod_perl support (a little weak at the moment)

• Choice of DB servers: SQLite (great for getting started/testing, but production is possible), PostgreSQL, MySQL, and other servers supported

• Use a fast static server to server CSS, JS, images, etc.

Page 216: Introduction to Jifty

Deployment

• Choice of web servers: FastCGI on Apache / Lighttpd, HTTP::Server::Simple, mod_perl support (a little weak at the moment)

• Choice of DB servers: SQLite (great for getting started/testing, but production is possible), PostgreSQL, MySQL, and other servers supported

• Use a fast static server to server CSS, JS, images, etc.

• Use CSS::Squish and JS::Squish to help compress and cache things

Page 217: Introduction to Jifty

Other Goodies

Page 218: Introduction to Jifty

Other Goodies

• Several authentication plugins: typical email sign-up login, OpenID, Facebook, LDAP, CAS

• Additional CRUD view helpers I haven’t demonstrated

• Built-in REST interface

• Full I18N support built-in

• Several Plugins for lots of things: Comments, Single Page Apps, Client-Side Templating, Charting, Tab helpers

• Built-in support for Comet (server push) in addition to Ajax

Page 219: Introduction to Jifty

Applications

Page 220: Introduction to Jifty

Applications

• Hiveminder (http://hiveminder.com)

Page 221: Introduction to Jifty

Applications

• Hiveminder (http://hiveminder.com)

• Wifty (http://jifty.org)

Page 222: Introduction to Jifty

Applications

• Hiveminder (http://hiveminder.com)

• Wifty (http://jifty.org)

• Qublog (http://qublog.net)

Page 223: Introduction to Jifty

Applications

• Hiveminder (http://hiveminder.com)

• Wifty (http://jifty.org)

• Qublog (http://qublog.net)

• Doxory (http://doxory.com)

Page 224: Introduction to Jifty

Applications

• Hiveminder (http://hiveminder.com)

• Wifty (http://jifty.org)

• Qublog (http://qublog.net)

• Doxory (http://doxory.com)

• CommitBit (http://code.bestpractical.com/)

Page 225: Introduction to Jifty

Applications

• Hiveminder (http://hiveminder.com)

• Wifty (http://jifty.org)

• Qublog (http://qublog.net)

• Doxory (http://doxory.com)

• CommitBit (http://code.bestpractical.com/)

• Ping / Chat / Clock (examples available with Jifty)

Page 226: Introduction to Jifty

Jifty Resources

Page 227: Introduction to Jifty

Jifty Resources

• CPAN (http://search.cpan.org/dist/Jifty/)

Page 228: Introduction to Jifty

Jifty Resources

• CPAN (http://search.cpan.org/dist/Jifty/)

• Jifty Wiki (http://jifty.org)

Page 229: Introduction to Jifty

Jifty Resources

• CPAN (http://search.cpan.org/dist/Jifty/)

• Jifty Wiki (http://jifty.org)

• Jifty SVN (http://svn.jifty.org/svn/jifty.org)

Page 230: Introduction to Jifty

Jifty Resources

• CPAN (http://search.cpan.org/dist/Jifty/)

• Jifty Wiki (http://jifty.org)

• Jifty SVN (http://svn.jifty.org/svn/jifty.org)

• Tutorial (http://search.cpan.org/dist/Jifty/lib/Jifty/Manual/Tutorial.pod)

Page 231: Introduction to Jifty

Jifty Resources

• CPAN (http://search.cpan.org/dist/Jifty/)

• Jifty Wiki (http://jifty.org)

• Jifty SVN (http://svn.jifty.org/svn/jifty.org)

• Tutorial (http://search.cpan.org/dist/Jifty/lib/Jifty/Manual/Tutorial.pod)

• Manual (http://search.cpan.org/dist/Jifty/lib/Jifty/Manual.pod)

Page 232: Introduction to Jifty

Jifty Resources

• CPAN (http://search.cpan.org/dist/Jifty/)

• Jifty Wiki (http://jifty.org)

• Jifty SVN (http://svn.jifty.org/svn/jifty.org)

• Tutorial (http://search.cpan.org/dist/Jifty/lib/Jifty/Manual/Tutorial.pod)

• Manual (http://search.cpan.org/dist/Jifty/lib/Jifty/Manual.pod)

• Mailing List: jifty‐[email protected]

Page 233: Introduction to Jifty

Jifty Resources

• CPAN (http://search.cpan.org/dist/Jifty/)

• Jifty Wiki (http://jifty.org)

• Jifty SVN (http://svn.jifty.org/svn/jifty.org)

• Tutorial (http://search.cpan.org/dist/Jifty/lib/Jifty/Manual/Tutorial.pod)

• Manual (http://search.cpan.org/dist/Jifty/lib/Jifty/Manual.pod)

• Mailing List: jifty‐[email protected]

• IRC Channel: #jifty on irc.freenode.org

Page 234: Introduction to Jifty

Qublog

• See http://qublog.net

• Sample code for QublogMini in SVN: http://qublog.net/svn/QublogMini

Page 235: Introduction to Jifty
Page 236: Introduction to Jifty

Thank you!