Loading...
Flash Player 9 (or above) is needed to view slideshows. We have detected that you do not have it on your computer.To install it, go here
Slideshow Transcript
- Slide 1: Jifty 1
- Slide 2: ⚁ 2
- Slide 3: 2007/04/01 3
- Slide 4: 2007/04/01 ⚁ 3
- Slide 5: 2007/04/01 ⚁ YAPC::Asia ⚁ 3
- Slide 6: 2007/04/01 ⚁ YAPC::Asia ⚁ : ! ⚁ 3
- Slide 7: <@ij1iao> JIT 4
- Slide 8: <@ij1iao> JIT 4
- Slide 9: <@ij1iao> JIT 4
- Slide 10: 5
- Slide 11: ⚁ 5
- Slide 12: ⚁ ? ⚁ 5
- Slide 13: ⚁ ? ⚁ : ! ⚁ 5
- Slide 14: 6
- Slide 15: 7
- Slide 16: 7
- Slide 17: 8
- Slide 18: 9
- Slide 19: ⚁ 9
- Slide 20: ⚁ ⚁ 9
- Slide 21: ⚁ ⚁ , ! ⚁ 9
- Slide 22: Pick! 10
- Slide 23: Pick! “ ” 10
- Slide 24: Pick! 11
- Slide 25: Pick! 11
- Slide 26: Pick! 12
- Slide 27: Pick! 12
- Slide 28: Pick! 13
- Slide 29: Pick! 13
- Slide 30: Pick! 14
- Slide 31: ... 15
- Slide 32: ... ! 16
- Slide 33: 17
- Slide 34: Jifty 18
- Slide 35: Jifty 18
- Slide 36: Jifty = 18
- Slide 37: Jifty = = 18
- Slide 38: Jifty = JFDI 19
- Slide 39: Jifty = JFDI Just F*cking Do It 19
- Slide 40: Jifty = JFDI Just F*cking Do It JFDI 19
- Slide 41: Jifty = JFDI Just F*cking Do It JFDI Doxory! 19
- Slide 42: 20
- Slide 43: • $ cpan 20
- Slide 44: • $ cpan • cpan> notest install Jifty 20
- Slide 45: • $ cpan • cpan> notest install Jifty “notest” . 20
- Slide 46: 21
- Slide 47: • $ jifty app ‐‐name Doxory 21
- Slide 48: • $ jifty app ‐‐name Doxory • Creating new application Doxory Creating directory lib Creating directory lib/Doxory Creating directory bin Creating directory etc Creating directory doc Creating directory log Creating directory var Creating directory var/mason Creating directory share Creating directory share/po Creating directory share/web Creating directory share/web/templates Creating directory share/web/static Creating directory lib/Doxory/Model Creating directory lib/Doxory/Action Creating directory t Creating configuration file Doxory/etc/config.yml 21
- Slide 49: 22
- Slide 50: bin/jifty 22
- Slide 51: bin/jifty etc/config.yml 22
- Slide 52: bin/jifty etc/config.yml Makefile.PL 22
- Slide 53: 23
- Slide 54: • $ jifty server 23
- Slide 55: • $ jifty server • INFO ‐ You can connect to your server at http://localhost:8888/ 23
- Slide 56: ! 24
- Slide 57: ! Doxory. (Users) ? 24
- Slide 58: 25
- Slide 59: • $ cd Doxory 25
- Slide 60: • $ cd Doxory • $ jifty model ‐‐name User 25
- Slide 61: • $ cd Doxory • $ jifty model ‐‐name User • Writing file t/00‐model‐User.t Writing file lib/Doxory/Model/User.pm 25
- Slide 62: • $ cd Doxory • $ jifty model ‐‐name User • Writing file t/00‐model‐User.t Writing file lib/Doxory/Model/User.pm • $ vim lib/Doxory/Model/User.pm 25
- Slide 63: • package Doxory::Model::User; • use Jifty::DBI::Schema; • • use Doxory::Record schema { • • • }; 26
- Slide 64: • package Doxory::Model::User; • use Jifty::DBI::Schema; • • use Doxory::Record schema { • • column name => • label is 'Username', • hints is 'Other people see this when you ask questions.', • is distinct, • is mandatory; • • column email => • label is 'Email', • hints is 'We will not sell it to anybody. Honest.', • default is '', • is distinct, • is immutable; • • }; 27
- Slide 65: 28
- Slide 66: • $ jifty schema ‐‐setup 28
- Slide 67: • $ jifty schema ‐‐setup • INFO ‐ Generating SQL for application Doxory... INFO ‐ Using Doxory::Model::User INFO ‐ Using Jifty::Model::Session INFO ‐ Using Jifty::Model::Metadata INFO ‐ Set up version v0.0.1, jifty version 0.701170 28
- Slide 68: • $ jifty schema ‐‐setup • INFO ‐ Generating SQL for application Doxory... INFO ‐ Using Doxory::Model::User INFO ‐ Using Jifty::Model::Session INFO ‐ Using Jifty::Model::Metadata INFO ‐ Set up version v0.0.1, jifty version 0.701170 • $ jifty server & 28
- Slide 69: • $ jifty schema ‐‐setup • INFO ‐ Generating SQL for application Doxory... INFO ‐ Using Doxory::Model::User INFO ‐ Using Jifty::Model::Session INFO ‐ Using Jifty::Model::Metadata INFO ‐ Set up version v0.0.1, jifty version 0.701170 • $ jifty server & • INFO ‐ You can connect to your server at http://localhost:8888/ 28
- Slide 70: • $ jifty schema ‐‐setup • INFO ‐ Generating SQL for application Doxory... INFO ‐ Using Doxory::Model::User INFO ‐ Using Jifty::Model::Session INFO ‐ Using Jifty::Model::Metadata INFO ‐ Set up version v0.0.1, jifty version 0.701170 • $ jifty server & • INFO ‐ You can connect to your server at http://localhost:8888/ • $ open http://localhost:8888/ 28
- Slide 71: 29
- Slide 72: 29
- Slide 73: 30
- Slide 74: 30
- Slide 75: 31
- Slide 76: 31
- Slide 77: 32
- Slide 78: 32
- Slide 79: 33
- Slide 80: AudreyT 33
- Slide 81: AudreyT 33
- Slide 82: 34
- Slide 83: (Choice) . 34
- Slide 84: 35
- Slide 85: $ jifty model ‐‐name Choice 35
- Slide 86: $ jifty model ‐‐name Choice Writing file t/00‐model‐Choice.t Writing file lib/Doxory/Model/Choice.pm 35
- Slide 87: $ jifty model ‐‐name Choice Writing file t/00‐model‐Choice.t Writing file lib/Doxory/Model/Choice.pm $ vim lib/Doxory/Model/Choice.pm 35
- Slide 88: • package Doxory::Model::Choice; • use Jifty::DBI::Schema; • use Doxory::Record schema { • • column name => • label is 'I need help deciding...', • render as 'textarea'; • • column a => • label is 'On the one hand', • render as 'textarea', is mandatory; • column b => • label is 'On the other hand', • render as 'textarea', is mandatory; • column asked_by => • label is 'Asked by', • default is defer { Jifty‐>web‐>current_user‐>id }, • references Doxory::Model::User; • • }; 36
- Slide 89: 37
- Slide 90: • $ jifty schema ‐‐drop‐database ‐‐setup 37
- Slide 91: • $ jifty schema ‐‐drop‐database ‐‐setup • INFO ‐ Generating SQL for application Doxory... INFO ‐ Using Doxory::Model::User INFO ‐ Using Doxory::Model::Choice INFO ‐ Using Jifty::Model::Session INFO ‐ Using Jifty::Model::Metadata INFO ‐ Set up version v0.0.1, jifty version 0.701170 37
- Slide 92: • $ jifty schema ‐‐drop‐database ‐‐setup • INFO ‐ Generating SQL for application Doxory... INFO ‐ Using Doxory::Model::User INFO ‐ Using Doxory::Model::Choice INFO ‐ Using Jifty::Model::Session INFO ‐ Using Jifty::Model::Metadata INFO ‐ Set up version v0.0.1, jifty version 0.701170 • $ open http://localhost:8888/ 37
- Slide 93: 38
- Slide 94: 38
- Slide 95: 39
- Slide 96: 39
- Slide 97: 40
- Slide 98: 40
- Slide 99: 41
- Slide 100: 41
- Slide 101: 42
- Slide 102: 42
- Slide 103: 43
- Slide 104: ! ... ? 43
- Slide 105: ✍ 44
- Slide 106: 45
- Slide 107: •$ vim etc/config.yml 45
- Slide 108: •$ vim etc/config.yml . 45
- Slide 109: •‐‐‐ •framework: • Plugins: • ‐ SkeletonApp: {} • ‐ REST: {} • ‐ Halo: {} • ‐ ErrorTemplates: {} • ‐ CompressedCSSandJS: {} • • • 46
- Slide 110: •‐‐‐ •framework: • Plugins: • ‐ SkeletonApp: {} • ‐ REST: {} • ‐ Halo: {} • ‐ ErrorTemplates: {} • ‐ CompressedCSSandJS: {} • ‐ Authentication::Password: {} • SkipAccessControl: 1 • 47
- Slide 111: •‐‐‐ •framework: • Plugins: • ‐ SkeletonApp: {} • ‐ REST: {} • ‐ Halo: {} • ‐ ErrorTemplates: {} • ‐ CompressedCSSandJS: {} • ‐ Authentication::Password: {} • SkipAccessControl: 1 • (ACL). 47
- Slide 112: 48
- Slide 113: •$ vim lib/Doxory/Model/User.pm 48
- Slide 114: •$ vim lib/Doxory/Model/User.pm User.pm mixin. 48
- Slide 115: • package Doxory::Model::User; • use Jifty::DBI::Schema; • use Doxory::Record schema { • • column name => • label is 'Username', • hints is 'Other people see this when you ask questions.', • is distinct, • is mandatory; • • column email => • label is 'Email', • hints is 'We will not sell it to anybody. Honest.', • default is '', • is distinct, • is immutable; • }; • 49
- Slide 116: • package Doxory::Model::User; • use Jifty::DBI::Schema; • use Doxory::Record schema { • • column name => • label is 'Username', • hints is 'Other people see this when you ask questions.', • is distinct, • is mandatory; • • column email => • label is 'Email', • hints is 'We will not sell it to anybody. Honest.', • default is '', • is distinct, • is immutable; • }; • use Jifty::Plugin::User::Mixin::Model::User; • use Jifty::Plugin::Authentication::Password::Mixin::Model::User; 50
- Slide 117: 51
- Slide 118: 51
- Slide 119: 52
- Slide 120: 52
- Slide 121: 53
- Slide 122: From: Doxory <> Date: April 3, 2007 5:43:07 PM JST To: jesse@bestpractical.com Subject: Doxory! ( ) Doxory . , : http://127.0.0.1:8888/let/jesse%40bestpractical.com/confirm_email/78f28e934cf6c058 53
- Slide 123: From: Doxory <> Date: April 3, 2007 5:43:07 PM JST To: jesse@bestpractical.com Subject: Doxory! ( ) Doxory . , : http://127.0.0.1:8888/let/jesse%40bestpractical.com/confirm_email/78f28e934cf6c058 53
- Slide 124: 54
- Slide 125: 54
- Slide 126: 55
- Slide 127: ... ( ?) 55
- Slide 128: ❁ 56
- Slide 129: 57
- Slide 130: •$ vim lib/Doxory/Dispatcher.pm 57
- Slide 131: •$ vim lib/Doxory/Dispatcher.pm Dispatcher (View). 57
- Slide 132: 58
- Slide 133: • package Doxory::Dispatcher; use Jifty::Dispatcher ‐base; 58
- Slide 134: • package Doxory::Dispatcher; use Jifty::Dispatcher ‐base; • before '*' => run { if (Jifty‐>web‐>current_user‐>id) { 58
- Slide 135: • package Doxory::Dispatcher; use Jifty::Dispatcher ‐base; • before '*' => run { if (Jifty‐>web‐>current_user‐>id) { • my $top = Jifty‐>web‐>navigation; $top‐>child( 'Choices' => url => '/choices' ); 58
- Slide 136: • package Doxory::Dispatcher; use Jifty::Dispatcher ‐base; • before '*' => run { if (Jifty‐>web‐>current_user‐>id) { • my $top = Jifty‐>web‐>navigation; $top‐>child( 'Choices' => url => '/choices' ); • } 58
- Slide 137: • package Doxory::Dispatcher; use Jifty::Dispatcher ‐base; • before '*' => run { if (Jifty‐>web‐>current_user‐>id) { • my $top = Jifty‐>web‐>navigation; $top‐>child( 'Choices' => url => '/choices' ); • } • elsif ($1 !~ /^login|^signup/) { tangent 'login'; } }; 58
- Slide 138: • package Doxory::Dispatcher; use Jifty::Dispatcher ‐base; • before '*' => run { if (Jifty‐>web‐>current_user‐>id) { • my $top = Jifty‐>web‐>navigation; $top‐>child( 'Choices' => url => '/choices' ); • } • elsif ($1 !~ /^login|^signup/) { tangent 'login'; } }; • # on '/' => show '/'; 58
- Slide 139: • package Doxory::Dispatcher; use Jifty::Dispatcher ‐base; • before '*' => run { if (Jifty‐>web‐>current_user‐>id) { • my $top = Jifty‐>web‐>navigation; $top‐>child( 'Choices' => url => '/choices' ); • } • elsif ($1 !~ /^login|^signup/) { tangent 'login'; } }; • # on '/' => show '/'; • # on '/choices' => show 'choices'; 58
- Slide 140: 59
- Slide 141: “/” . 59
- Slide 142: 60
- Slide 143: •$ vim lib/Doxory/View.pm 60
- Slide 144: •$ vim lib/Doxory/View.pm TT2 ! Mason ! 60
- Slide 145: 61
- Slide 146: • package Doxory::View; use Jifty::View::Declare ‐base; 61
- Slide 147: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { h1 { 'Ask a question!' } 61
- Slide 148: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { h1 { 'Ask a question!' } • show 'new_choice'; 61
- Slide 149: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { h1 { 'Ask a question!' } • show 'new_choice'; • }; 61
- Slide 150: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { h1 { 'Ask a question!' } • show 'new_choice'; • }; • private template new_choice => sub { div { form { 61
- Slide 151: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { h1 { 'Ask a question!' } • show 'new_choice'; • }; • private template new_choice => sub { div { form { • my $action = new_action( class => 'CreateChoice' ); 61
- Slide 152: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { h1 { 'Ask a question!' } • show 'new_choice'; • }; • private template new_choice => sub { div { form { • my $action = new_action( class => 'CreateChoice' ); • render_action( $action => ['name', 'a', 'b'] ); 61
- Slide 153: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { h1 { 'Ask a question!' } • show 'new_choice'; • }; • private template new_choice => sub { div { form { • my $action = new_action( class => 'CreateChoice' ); • render_action( $action => ['name', 'a', 'b'] ); • form_submit( label => 'Ask the Crowd!' ); 61
- Slide 154: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { h1 { 'Ask a question!' } • show 'new_choice'; • }; • private template new_choice => sub { div { form { • my $action = new_action( class => 'CreateChoice' ); • render_action( $action => ['name', 'a', 'b'] ); • form_submit( label => 'Ask the Crowd!' ); • } } 61
- Slide 155: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { h1 { 'Ask a question!' } • show 'new_choice'; • }; • private template new_choice => sub { div { form { • my $action = new_action( class => 'CreateChoice' ); • render_action( $action => ['name', 'a', 'b'] ); • form_submit( label => 'Ask the Crowd!' ); • } } • }; 61
- Slide 156: 62
- Slide 157: 62
- Slide 158: 63
- Slide 159: column a => label is 'On the one hand', render as 'textarea', is mandatory; 63
- Slide 160: 64
- Slide 161: 64
- Slide 162: 65
- Slide 163: “choices” . 65
- Slide 164: •$ vim lib/Doxory/View.pm 66
- Slide 165: 67
- Slide 166: • package Doxory::View; use Jifty::View::Declare ‐base; 67
- Slide 167: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { ... }; private template new_choice => sub { ... }; 67
- Slide 168: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { ... }; private template new_choice => sub { ... }; • template choices => page { 67
- Slide 169: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { ... }; private template new_choice => sub { ... }; • template choices => page { • h1 { 'My Choices' } dl { 67
- Slide 170: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { ... }; private template new_choice => sub { ... }; • template choices => page { • h1 { 'My Choices' } dl { • my $choices = Doxory::Model::ChoiceCollection‐>new; $choices‐>limit( column => 'asked_by', value => Jifty‐>web‐>current_user‐>id, ); 67
- Slide 171: • package Doxory::View; use Jifty::View::Declare ‐base; • template '/' => page { ... }; private template new_choice => sub { ... }; • template choices => page { • h1 { 'My Choices' } dl { • my $choices = Doxory::Model::ChoiceCollection‐>new; $choices‐>limit( column => 'asked_by', value => Jifty‐>web‐>current_user‐>id, ); • while (my $c = $choices‐>next) { dt { $c‐>name, ' (', $c‐>asked_by‐>name, ')' } dd { b { $c‐>a } em { 'vs' } b { $c‐>b } } } } }; 67
- Slide 172: 68
- Slide 173: ... ? 68
- Slide 174: ☑ 69
- Slide 175: 70
- Slide 176: • $ jifty model ‐‐name Vote 70
- Slide 177: • $ jifty model ‐‐name Vote • Writing file t/00‐model‐Vote.t Writing file lib/Doxory/Model/Vote.pm 70
- Slide 178: • $ jifty model ‐‐name Vote • Writing file t/00‐model‐Vote.t Writing file lib/Doxory/Model/Vote.pm • $ vim lib/Doxory/Model/Vote.pm 70
- Slide 179: • package Doxory::Model::Vote; • use Jifty::DBI::Schema; • use Doxory::Record schema { • • column choice => • references Doxory::Model::Choice; • • column voter => • references Doxory::Model::User; • column suggestion => • valid are qw( a b skip ); • column comments => • label is 'Comments?', • render as 'textarea’; • • }; 71
- Slide 180: 72
- Slide 181: 72
- Slide 182: 73
- Slide 183: “pick” . 73
- Slide 184: •$ vim lib/Doxory/Dispatcher.pm 74
- Slide 185: •$ vim lib/Doxory/Dispatcher.pm /pick . 74
- Slide 186: • package Doxory::Dispatcher; use Jifty::Dispatcher ‐base; • before '*' => run { if (Jifty‐>web‐>current_user‐>id) { • my $top = Jifty‐>web‐>navigation; • $top‐>child( 'Pick!' => url => '/pick' ); • $top‐>child( 'Choices' => url => '/choices' ); • } • elsif ($1 !~ /^login|^signup/) { • tangent 'login'; } • }; • on '/' => show 'new_choice'; 75
- Slide 187: • package Doxory::Dispatcher; • ... • on pick => run { • my $choices = Doxory::Model::ChoiceCollection‐>new; • my $votes = $choices‐>join( • type => 'left', • alias1 => 'main', column1 => 'id', • table2 => 'votes', column2 => 'choice', • ); • $choices‐>limit( • leftjoin => $votes, column => 'voter', • value => Jifty‐>web‐>current_user‐>id, • ); • $choices‐>limit( • alias => $votes, column => 'voter', • operator => 'IS', value => 'NULL', • ); • if (my $c = $choices‐>first) { • set choice => $c; • } • else { • show 'nothing_to_pick'; • } • }; 76
- Slide 188: • package Doxory::Dispatcher; • ... • on pick => run { • my $choices = Doxory::Model::ChoiceCollection‐>new; • my $votes = $choices‐>join( • type => 'left', • alias1 => 'main', column1 => 'id', • table2 => 'votes', column2 => 'choice', • ); • $choices‐>limit( • leftjoin => $votes, column => 'voter', • value => Jifty‐>web‐>current_user‐>id, • ); • $choices‐>limit( • alias => $votes, column => 'voter', • operator => 'IS', value => 'NULL', • ); • if (my $c = $choices‐>first) { • set choice => $c; • } “ ” • else { • show 'nothing_to_pick'; • } • }; 76
- Slide 189: •$ vim lib/Doxory/View.pm 77
- Slide 190: 78
- Slide 191: • package Doxory::View; 78
- Slide 192: • package Doxory::View; • use Jifty::View::Declare ‐base; template '' => page { ... }; private template choices => sub { ... }; 78
- Slide 193: • package Doxory::View; • use Jifty::View::Declare ‐base; template '' => page { ... }; private template choices => sub { ... }; • template pick => page { 78
- Slide 194: • package Doxory::View; • use Jifty::View::Declare ‐base; template '' => page { ... }; private template choices => sub { ... }; • template pick => page { • my $choice = get('choice'); 78
- Slide 195: • package Doxory::View; • use Jifty::View::Declare ‐base; template '' => page { ... }; private template choices => sub { ... }; • template pick => page { • my $choice = get('choice'); • my $action = new_action( class => 'CreateVote' ); 78
- Slide 196: • package Doxory::View; • use Jifty::View::Declare ‐base; template '' => page { ... }; private template choices => sub { ... }; • template pick => page { • my $choice = get('choice'); • my $action = new_action( class => 'CreateVote' ); • my $redir = new_action( class => "Jifty::Action::Redirect", arguments => { url => '/pick' }, ); 78
- Slide 197: • package Doxory::View; • use Jifty::View::Declare ‐base; template '' => page { ... }; private template choices => sub { ... }; • template pick => page { • my $choice = get('choice'); • my $action = new_action( class => 'CreateVote' ); • my $redir = new_action( class => "Jifty::Action::Redirect", arguments => { url => '/pick' }, ); • my %args = ( choice => $choice‐>id, voter => Jifty‐>web‐>current_user‐>id, ); 78
- Slide 198: • package Doxory::View; • use Jifty::View::Declare ‐base; template '' => page { ... }; private template choices => sub { ... }; • template pick => page { • my $choice = get('choice'); • my $action = new_action( class => 'CreateVote' ); • my $redir = new_action( class => "Jifty::Action::Redirect", arguments => { url => '/pick' }, ); • my %args = ( choice => $choice‐>id, voter => Jifty‐>web‐>current_user‐>id, ); • h1 { $choice‐>asked_by‐>name, ': ', $choice‐>name } 78
- Slide 199: • package Doxory::View; • use Jifty::View::Declare ‐base; template '' => page { ... }; private template choices => sub { ... }; • template pick => page { • my $choice = get('choice'); • my $action = new_action( class => 'CreateVote' ); • my $redir = new_action( class => "Jifty::Action::Redirect", arguments => { url => '/pick' }, ); • my %args = ( choice => $choice‐>id, voter => Jifty‐>web‐>current_user‐>id, ); • h1 { $choice‐>asked_by‐>name, ': ', $choice‐>name } • div { form { 78
- Slide 200: • package Doxory::View; • use Jifty::View::Declare ‐base; template '' => page { ... }; private template choices => sub { ... }; • template pick => page { • my $choice = get('choice'); • my $action = new_action( class => 'CreateVote' ); • my $redir = new_action( class => "Jifty::Action::Redirect", arguments => { url => '/pick' }, ); • my %args = ( choice => $choice‐>id, voter => Jifty‐>web‐>current_user‐>id, ); • h1 { $choice‐>asked_by‐>name, ': ', $choice‐>name } • div { form { • my ($x, $y) = map { $action‐>button( submit => [ $action, $redir ], label => $choice‐>$_, arguments => { suggestion => $_, %args }, ) } ((rand > 0.5) ? ('a', 'b') : ('b', 'a')); 78
- Slide 201: • package Doxory::View; • use Jifty::View::Declare ‐base; template '' => page { ... }; private template choices => sub { ... }; • template pick => page { • my $choice = get('choice'); • my $action = new_action( class => 'CreateVote' ); • my $redir = new_action( class => "Jifty::Action::Redirect", arguments => { url => '/pick' }, ); • my %args = ( choice => $choice‐>id, voter => Jifty‐>web‐>current_user‐>id, ); • h1 { $choice‐>asked_by‐>name, ': ', $choice‐>name } • div { form { • my ($x, $y) = map { $action‐>button( submit => [ $action, $redir ], label => $choice‐>$_, arguments => { suggestion => $_, %args }, ) } ((rand > 0.5) ? ('a', 'b') : ('b', 'a')); • span { $x } em { 'or' } span { $y } em { 'or' } span { $action‐>button( submit => [ $action, $redir ], label => 'None of the above', arguments => { suggestion => 'skip', %args }, ); } p { render_param( $action => 'comments' ) } } } }; 78
- Slide 202: 79
- Slide 203: • package Doxory::View; use Jifty::View::Declare ‐base; template '' => page { ... }; private template new_choice => sub { ... }; template choices => page { ... }; template pick => page { ... }; 79
- Slide 204: • package Doxory::View; use Jifty::View::Declare ‐base; template '' => page { ... }; private template new_choice => sub { ... }; template choices => page { ... }; template pick => page { ... }; • template nothing_to_pick => page { h1 { "There's nothing for you to pick." } 79
- Slide 205: • package Doxory::View; use Jifty::View::Declare ‐base; template '' => page { ... }; private template new_choice => sub { ... }; template choices => page { ... }; template pick => page { ... }; • template nothing_to_pick => page { h1 { "There's nothing for you to pick." } • p { "No one you know is angsting about anything. Everybody knows where they're going to dinner, what to do on their next date and whether to drop that class. You have such lovely and well adjusted friends." } 79
- Slide 206: • package Doxory::View; use Jifty::View::Declare ‐base; template '' => page { ... }; private template new_choice => sub { ... }; template choices => page { ... }; template pick => page { ... }; • template nothing_to_pick => page { h1 { "There's nothing for you to pick." } • p { "No one you know is angsting about anything. Everybody knows where they're going to dinner, what to do on their next date and whether to drop that class. You have such lovely and well adjusted friends." } • h2 { "Maybe it's time to ask for some advice..." }; 79
- Slide 207: • package Doxory::View; use Jifty::View::Declare ‐base; template '' => page { ... }; private template new_choice => sub { ... }; template choices => page { ... }; template pick => page { ... }; • template nothing_to_pick => page { h1 { "There's nothing for you to pick." } • p { "No one you know is angsting about anything. Everybody knows where they're going to dinner, what to do on their next date and whether to drop that class. You have such lovely and well adjusted friends." } • h2 { "Maybe it's time to ask for some advice..." }; • show 'new_choice'; }; 79
- Slide 208: 80
- Slide 209: 81
- Slide 210: 81
- Slide 211: 82
- Slide 212: choices , . 82
- Slide 213: •$ vim lib/Doxory/Model/Choice.pm 83
- Slide 214: • package Doxory::Model::Choice; • use Jifty::DBI::Schema; • use Doxory::Record schema { ... } • sub in_favor_of_a { • my $self = shift; • $self‐>in_favor_of('a'); • } • sub in_favor_of_b { • my $self = shift; • $self‐>in_favor_of('b'); • } • sub in_favor_of { • my ($self, $x) = @_; • my $votes = Doxory::Model::VoteCollection‐>new; • $votes‐>limit(column => 'choice', value => $self‐>id); • $votes‐>limit(column => 'suggestion', value => $x); • return $votes; • } • 84
- Slide 215: •$ vim lib/Doxory/View.pm 85
- Slide 216: 86
- Slide 217: 86
- Slide 218: • package Doxory::View; use Jifty::View::Declare ‐base; ... 86
- Slide 219: • package Doxory::View; use Jifty::View::Declare ‐base; ... • template choices => page { h1 { 'My Choices' } 86
- Slide 220: • package Doxory::View; use Jifty::View::Declare ‐base; ... • template choices => page { h1 { 'My Choices' } • dl { 86
- Slide 221: • package Doxory::View; use Jifty::View::Declare ‐base; ... • template choices => page { h1 { 'My Choices' } • dl { • my $choices = Doxory::Model::ChoiceCollection‐>new; $choices‐>limit( column => 'asked_by', value => Jifty‐>web‐>current_user‐>id, ); 86
- Slide 222: • package Doxory::View; use Jifty::View::Declare ‐base; ... • template choices => page { h1 { 'My Choices' } • dl { • my $choices = Doxory::Model::ChoiceCollection‐>new; $choices‐>limit( column => 'asked_by', value => Jifty‐>web‐>current_user‐>id, ); • while (my $c = $choices‐>next) { dt { $c‐>name, ' (', $c‐>asked_by‐>name, ')' } dd { 86
- Slide 223: • package Doxory::View; use Jifty::View::Declare ‐base; ... • template choices => page { h1 { 'My Choices' } • dl { • my $choices = Doxory::Model::ChoiceCollection‐>new; $choices‐>limit( column => 'asked_by', value => Jifty‐>web‐>current_user‐>id, ); • while (my $c = $choices‐>next) { dt { $c‐>name, ' (', $c‐>asked_by‐>name, ')' } dd { • b { $c‐>a, ' (', $c‐>in_favor_of_a‐>count, ')' } 86
- Slide 224: • package Doxory::View; use Jifty::View::Declare ‐base; ... • template choices => page { h1 { 'My Choices' } • dl { • my $choices = Doxory::Model::ChoiceCollection‐>new; $choices‐>limit( column => 'asked_by', value => Jifty‐>web‐>current_user‐>id, ); • while (my $c = $choices‐>next) { dt { $c‐>name, ' (', $c‐>asked_by‐>name, ')' } dd { • b { $c‐>a, ' (', $c‐>in_favor_of_a‐>count, ')' } • em { 'vs' } 86
- Slide 225: • package Doxory::View; use Jifty::View::Declare ‐base; ... • template choices => page { h1 { 'My Choices' } • dl { • my $choices = Doxory::Model::ChoiceCollection‐>new; $choices‐>limit( column => 'asked_by', value => Jifty‐>web‐>current_user‐>id, ); • while (my $c = $choices‐>next) { dt { $c‐>name, ' (', $c‐>asked_by‐>name, ')' } dd { • b { $c‐>a, ' (', $c‐>in_favor_of_a‐>count, ')' } • em { 'vs' } • b { $c‐>b, ' (', $c‐>in_favor_of_b‐>count, ')' } 86
- Slide 226: • package Doxory::View; use Jifty::View::Declare ‐base; ... • template choices => page { h1 { 'My Choices' } • dl { • my $choices = Doxory::Model::ChoiceCollection‐>new; $choices‐>limit( column => 'asked_by', value => Jifty‐>web‐>current_user‐>id, ); • while (my $c = $choices‐>next) { dt { $c‐>name, ' (', $c‐>asked_by‐>name, ')' } dd { • b { $c‐>a, ' (', $c‐>in_favor_of_a‐>count, ')' } • em { 'vs' } • b { $c‐>b, ' (', $c‐>in_favor_of_b‐>count, ')' } • } } } }; 86
- Slide 227: 87
- Slide 228: : . ☺ 87
- Slide 229: ! 88
- Slide 230: ! lib/Doxory/Model/User.pm 88
- Slide 231: ! lib/Doxory/Model/User.pm lib/Doxory/Model/Choice.pm 88
- Slide 232: ! lib/Doxory/Model/User.pm lib/Doxory/Model/Choice.pm lib/Doxory/Model/Vote.pm 88
- Slide 233: ! lib/Doxory/Model/User.pm lib/Doxory/Model/Choice.pm lib/Doxory/Model/Vote.pm lib/Doxory/Dispatcher.pm 88
- Slide 234: ! lib/Doxory/Model/User.pm lib/Doxory/Model/Choice.pm lib/Doxory/Model/Vote.pm lib/Doxory/Dispatcher.pm lib/Doxory/View.pm 88
- Slide 235: ! lib/Doxory/Model/User.pm lib/Doxory/Model/Choice.pm lib/Doxory/Model/Vote.pm lib/Doxory/Dispatcher.pm lib/Doxory/View.pm 88
- Slide 236: ☈ 89
- Slide 237: 90
- Slide 238: ☈ Doxory 90
- Slide 239: ☈ Doxory ☈ 90
- Slide 240: ☈ Doxory ☈ ☈ ... 90
- Slide 241: Doxory 91
- Slide 242: Doxory ☈ ! 91
- Slide 243: Doxory ☈ ! ☈ 91
- Slide 244: Doxory ☈ ! ☈ ☈ vim lib/Doxory/Model/Choice.pm 91
- Slide 245: 92
- Slide 246: • package Doxory::Model::Choice; 92
- Slide 247: • package Doxory::Model::Choice; • use Regexp::Common 'profanity_us'; 92
- Slide 248: • package Doxory::Model::Choice; • use Regexp::Common 'profanity_us'; • sub validate_name { my ($self, $name) = @_; 92
- Slide 249: • package Doxory::Model::Choice; • use Regexp::Common 'profanity_us'; • sub validate_name { my ($self, $name) = @_; • if ($name =~ /$RE{profanity}/i) { return ( 0, 'Would you speak like that '. 'in front of your mother? *cough*' ); } 92
- Slide 250: • package Doxory::Model::Choice; • use Regexp::Common 'profanity_us'; • sub validate_name { my ($self, $name) = @_; • if ($name =~ /$RE{profanity}/i) { return ( 0, 'Would you speak like that '. 'in front of your mother? *cough*' ); } • return 1; } 92
- Slide 251: 93
- Slide 252: (Validator) 94
- Slide 253: (Validator) ☈ 94
- Slide 254: (Validator) ☈ ☈ 94
- Slide 255: (Validator) ☈ ☈ ☈ ! 94
- Slide 256: • package Doxory::Model::Choice; use Regexp::Common 'profanity_us'; • sub canonicalize_name { • my ($self, $name) = @_; • $name =~ s/$RE{profanity}/**expletives**/gi; • return $name; •} 95
- Slide 257: 96
- Slide 258: (Canonicalizer) 97
- Slide 259: (Canonicalizer) ☈ Model 97
- Slide 260: (Canonicalizer) ☈ Model ☈ (Autocompleter) 97
- Slide 261: (Canonicalizer) ☈ Model ☈ (Autocompleter) ☈ : Doxory 97
- Slide 262: 98
- Slide 263: •$ vim lib/Doxory/Dispatcher.pm 99
- Slide 264: •$ vim lib/Doxory/Dispatcher.pm . 99
- Slide 265: • package Doxory::Dispatcher; use Jifty::Dispatcher ‐base; • before '*' => run { if (Jifty‐>web‐>current_user‐>id) { • my $top = Jifty‐>web‐>navigation; • $top‐>child( 'Pick!' => url => '/pick' ); • $top‐>child( 'Choices' => url => '/choices' ); • } • elsif ($1 !~ /^login|^signup/) { • tangent 'login'; } • }; • ... 100
- Slide 266: • package Doxory::Dispatcher; use Jifty::Dispatcher ‐base; • before '*' => run { if (Jifty‐>web‐>current_user‐>id) { • my $top = Jifty‐>web‐>navigation; • $top‐>child( _('Pick!') => url => '/pick' ); • $top‐>child( _('Choices') => url => '/choices' ); • } • elsif ($1 !~ /^login|^signup/) { • tangent 'login'; } • }; • ... 101
- Slide 267: •$ vim lib/Doxory/Model/*.pm 102
- Slide 268: •$ vim lib/Doxory/Model/*.pm label, hints . 102
- Slide 269: • package Doxory::Model::Choice; • use Jifty::DBI::Schema; • use Doxory::Record schema { • • column name => • label is _('I need help deciding...'), • render as 'textarea'; • • column a => • label is _('On the one hand'), • render as 'textarea', is mandatory; • column b => • label is _('On the other hand'), • render as 'textarea', is mandatory; • column asked_by => • label is _('Asked by'), • default is defer { Jifty‐>web‐>current_user‐>id }, • references Doxory::Model::User; • • }; 103
- Slide 270: package Doxory::Model::User; use Jifty::DBI::Schema; use Doxory::Record schema { column name => label is _('Username'), hints is _('Other people see this when you ask questions.'), is distinct, is mandatory; column email => label is _('Email'), hints is _('We will not sell it to anybody. Honest.'), default is '', is distinct, is immutable; }; 104
- Slide 271: • package Doxory::Model::Vote; • use Jifty::DBI::Schema; • use Doxory::Record schema { • • column choice => • references Doxory::Model::Choice; • • column voter => • references Doxory::Model::User; • column suggestion => • valid are qw( a b skip ); • column comments => • label is _('Comments?'), • render as 'textarea’; • • }; 105
- Slide 272: •$ vim lib/Doxory/View.pm 106
- Slide 273: •$ vim lib/Doxory/View.pm . 106
- Slide 274: • package Doxory::View; use Jifty::View::Declare ‐base; template '/' => page { h1 { _('Ask a question!') } • show 'new_choice'; • }; • private template new_choice => sub { div { form { • my $action = new_action( class => 'CreateChoice' ); • render_action( $action => ['name', 'a', 'b'] ); • form_submit( label => _('Ask the Crowd!') ); • } } • }; • ... 107
- Slide 275: 108
- Slide 276: • $ jifty po ‐‐language zh_tw 108
- Slide 277: . • $ jifty po ‐‐language zh_tw 108
- Slide 278: . • $ jifty po ‐‐language zh_tw • INFO ‐ Extracting messages from 'lib/Doxory/Dispatcher.pm' INFO ‐ Extracting messages from 'lib/Doxory/View.pm' INFO ‐ Extracting messages from 'lib/Doxory/Model/Choice.pm' INFO ‐ Extracting messages from 'lib/Doxory/Model/User.pm' INFO ‐ Extracting messages from 'lib/Doxory/Model/Vote.pm' INFO ‐ Extracting messages from 'bin/jifty' INFO ‐ Updating message catalog 'share/po/zh_tw.po' 108
- Slide 279: . • $ jifty po ‐‐language zh_tw • INFO ‐ Extracting messages from 'lib/Doxory/Dispatcher.pm' INFO ‐ Extracting messages from 'lib/Doxory/View.pm' INFO ‐ Extracting messages from 'lib/Doxory/Model/Choice.pm' INFO ‐ Extracting messages from 'lib/Doxory/Model/User.pm' INFO ‐ Extracting messages from 'lib/Doxory/Model/Vote.pm' INFO ‐ Extracting messages from 'bin/jifty' INFO ‐ Updating message catalog 'share/po/zh_tw.po' • $ vim share/po/zh_tw.po 108
- Slide 280: . • $ jifty po ‐‐language zh_tw • INFO ‐ Extracting messages from 'lib/Doxory/Dispatcher.pm' INFO ‐ Extracting messages from 'lib/Doxory/View.pm' INFO ‐ Extracting messages from 'lib/Doxory/Model/Choice.pm' INFO ‐ Extracting messages from 'lib/Doxory/Model/User.pm' INFO ‐ Extracting messages from 'lib/Doxory/Model/Vote.pm' INFO ‐ Extracting messages from 'bin/jifty' INFO ‐ Updating message catalog 'share/po/zh_tw.po' • $ vim share/po/zh_tw.po . 108
- Slide 281: msgid "" msgstr "" "Content‐Type: text/plain; charset=CHARSET " • #: lib/Doxory/Model/Choice.pm:9 #: lib/Doxory/View.pm:8 • msgid "I need help deciding..." msgid "Ask a question!" • msgstr "" msgstr "" • #: lib/Doxory/Model/Choice.pm:13 #: lib/Doxory/View.pm:16 • msgid "On the one hand" msgid "Ask the crowd!" • msgstr "" msgstr "" • #: lib/Doxory/Model/Choice.pm:18 #: lib/Doxory/Model/Choice.pm:23 • msgid "On the other hand" msgid "Asked by" • msgstr "" msgstr "" • #: lib/Doxory/Dispatcher.pm:9 #: lib/Doxory/Dispatcher.pm:10 • msgid "Pick!" msgid "Choices" • msgstr "" msgstr "" • #: lib/Doxory/Model/Vote.pm:18 msgid "Comments?" msgstr "" 109
- Slide 282: msgid "" msgstr "" "Content‐Type: text/plain; charset=UTF‐8 " • #: lib/Doxory/Model/Choice.pm:9 #: lib/Doxory/View.pm:8 • msgid "I need help deciding..." msgid "Ask a question!" • msgstr " , ..." msgstr " !" • #: lib/Doxory/Model/Choice.pm:13 #: lib/Doxory/View.pm:16 • msgid "On the one hand" msgid "Ask the crowd!" • msgstr " ...?" msgstr " !" • #: lib/Doxory/Model/Choice.pm:18 #: lib/Doxory/Model/Choice.pm:23 • msgid "On the other hand" msgid "Asked by" • msgstr " ...?" msgstr " " • #: lib/Doxory/Dispatcher.pm:9 #: lib/Doxory/Dispatcher.pm:10 • msgid "Pick!" msgid "Choices" • msgstr " !" msgstr " " • #: lib/Doxory/Model/Vote.pm:18 msgid "Comments?" msgstr " ?" 110
- Slide 283: 111
- Slide 284: ... 111
- Slide 285: 112
- Slide 286: • $ b2g.pl ‐p ‐u share/po/zh_tw.po > share/po/zh_cn.po 112
- Slide 287: Encode::HanConvert . • $ b2g.pl ‐p ‐u share/po/zh_tw.po > share/po/zh_cn.po 112
- Slide 288: Encode::HanConvert . • $ b2g.pl ‐p ‐u share/po/zh_tw.po > share/po/zh_cn.po • $ vim etc/config.yml 112
- Slide 289: Encode::HanConvert . • $ b2g.pl ‐p ‐u share/po/zh_tw.po > share/po/zh_cn.po • $ vim etc/config.yml . 强 设 112
- Slide 290: •‐‐‐ •framework: • L10N: • PoDir: share/po • 113
- Slide 291: •‐‐‐ •framework: • L10N: • PoDir: share/po • Lang: zh‐cn • 114
- Slide 292: 115
- Slide 293: ! 国际 115
- Slide 294: 116
- Slide 295: 117
- Slide 296: HTTP 117
- Slide 297: HTTP Module::Install 117
- Slide 298: HTTP Module::Install PAR 117
- Slide 299: (Halo) 118
- Slide 300: (Halo) 118
- Slide 301: (Halo) 118
- Slide 302: (Halo) ... ! 118
- Slide 303: Halo 119
- Slide 304: Halo SQL 119
- Slide 305: Halo SQL SQL 119
- Slide 306: Halo SQL SQL 119
- Slide 307: Halo SQL SQL 119
- Slide 308: (DevelMode) 120
- Slide 309: (DevelMode) Module::Refresh 120
- Slide 310: (DevelMode) Module::Refresh Log4Perl 120
- Slide 311: (DevelMode) Module::Refresh Log4Perl 120
- Slide 312: 121
- Slide 313: Lighttpd / Apache 121
- Slide 314: Lighttpd / Apache CSS::Squish 121
- Slide 315: Lighttpd / Apache CSS::Squish JavaScript::Squish 121
- Slide 316: ... 122
- Slide 317: ... I18N 122
- Slide 318: ... I18N Session 122
- Slide 319: ... I18N Session (Event) 122
- Slide 320: ✈ 123
- Slide 321: 124
- Slide 322: ✈ Wiki UI 124
- Slide 323: ✈ Wiki UI ✈ , 124
- Slide 324: ✈ Wiki UI ✈ , ✈ , , MTV... 124
- Slide 325: 125
- Slide 326: ✈ Wifty 125
- Slide 327: ✈ Wifty ✈ CommitBit 125
- Slide 328: ✈ Wifty ✈ CommitBit ✈ BabelBee 125
- Slide 329: ✈ Ping ✈ Wifty ✈ CommitBit ✈ BabelBee 125
- Slide 330: ✈ Ping ✈ Wifty ✈ Chat ✈ CommitBit ✈ BabelBee 125
- Slide 331: ✈ Ping ✈ Wifty ✈ Chat ✈ CommitBit ✈ Clock ✈ BabelBee 125
- Slide 332: ✈ Ping ✈ Wifty ✈ Chat ✈ CommitBit ✈ Clock ✈ BabelBee ✈ Doxory! 125
- Slide 333: Jifty 126
- Slide 334: Jifty ✈ cpan Jifty 126
- Slide 335: Jifty ✈ cpan Jifty ✈ http://svn.jifty.org/svn/jifty.org 126
- Slide 336: Jifty ✈ cpan Jifty ✈ http://svn.jifty.org/svn/jifty.org ✈ http://jifty.org/ 126
- Slide 337: 127
- Slide 338: ✈ Jifty::Manual::Tutorial 127
- Slide 339: ✈ Jifty::Manual::Tutorial ✈ irc.freenode.net #jifty 127
- Slide 340: ✈ Jifty::Manual::Tutorial ✈ irc.freenode.net #jifty ✈ jifty‐devel@lists.jifty.org 127
- Slide 341: fin. 128
- Slide 342: Bonus Slides 129
- Slide 343: ☺ 130
- Slide 344: Anatomy of a Jifty App 131
- Slide 345: Anatomy of a Jifty App ☺ Model : Columns 131
- Slide 346: Anatomy of a Jifty App ☺ Model : Columns ☺ Action : Parameters 131
- Slide 347: Anatomy of a Jifty App ☺ Model : Columns ☺ Action : Parameters ☺ Template : Fragments 131
- Slide 348: More Components 132
- Slide 349: More Components ☺ Dispatcher 132
- Slide 350: More Components ☺ Dispatcher ☺ ClassLoader 132
- Slide 351: More Components ☺ Dispatcher ☺ ClassLoader ☺ Continuations 132
- Slide 352: ䷗ 133
- Slide 353: Jifty::DBI 134
- Slide 354: Jifty::DBI ∅ CREATE TABLE 134
- Slide 355: Jifty::DBI ∅ CREATE TABLE ∅ ALTER TABLE 134
- Slide 356: Jifty::DBI ∅ CREATE TABLE ∅ ALTER TABLE ∅ CREATE FOREIGN KEY 134
- Slide 357: Object Relational Mapper 135
- Slide 358: Object Relational Mapper ∅ SELECT 135
- Slide 359: Object Relational Mapper ∅ SELECT ∅ INSERT 135
- Slide 360: Object Relational Mapper ∅ SELECT ∅ UPDATE ∅ INSERT 135
- Slide 361: Object Relational Mapper ∅ SELECT ∅ UPDATE ∅ INSERT ∅ DELETE 135
- Slide 362: Jifty::DBI::Handle 136
- Slide 363: Jifty::DBI::Handle ䷗ SQLite 136
- Slide 364: Jifty::DBI::Handle ䷗ SQLite ䷗ Postgres 136
- Slide 365: Jifty::DBI::Handle ䷗ SQLite ䷗ MySQL ䷗ Postgres 136
- Slide 366: Jifty::DBI::Handle ䷗ SQLite ䷗ MySQL ䷗ Postgres ䷗ Oracle 136
- Slide 367: Jifty::DBI::Collection 137
- Slide 368: Jifty::DBI::Collection ䷗ Joins and Limits 137
- Slide 369: Jifty::DBI::Collection ䷗ Joins and Limits ䷗ Paging = Data::Page 137
- Slide 370: Jifty::DBI::Collection ䷗ Joins and Limits ䷗ Paging = Data::Page ䷗ Caching = Memcached 137
- Slide 371: Jifty::DBI::Schema 138
- Slide 372: Jifty::DBI::Schema ䷗ Declarative Columns 138
- Slide 373: Jifty::DBI::Schema ䷗ Declarative Columns ䷗ Remember our Doxory? 138
- Slide 374: Jifty::DBI::Schema ䷗ Declarative Columns ䷗ Remember our Doxory? ䷗ Time for 0.0.2! 138
- Slide 375: 139
- Slide 376: • package Doxory::Model::Comment; use Jifty::DBI::Schema; use Doxory::Record schema { since '0.0.2'; 139
- Slide 377: • package Doxory::Model::Comment; use Jifty::DBI::Schema; use Doxory::Record schema { since '0.0.2'; • column User => refers to Doxory::Model:User; column author => refers to Doxory::Model::User; 139
- Slide 378: • package Doxory::Model::Comment; use Jifty::DBI::Schema; use Doxory::Record schema { since '0.0.2'; • column User => refers to Doxory::Model:User; column author => refers to Doxory::Model::User; • column body => label is 'Content', type is 'Text', render as 'Textarea', default is 'First Post!'; 139
- Slide 379: • package Doxory::Model::Comment; use Jifty::DBI::Schema; use Doxory::Record schema { since '0.0.2'; • column User => refers to Doxory::Model:User; column author => refers to Doxory::Model::User; • column body => label is 'Content',

