Upload
gea-suan-lin
View
3.055
Download
0
Embed Size (px)
DESCRIPTION
Jifty by Audrey Tang in OSDC.tw 2007
Citation preview
Jifty♨
唐鳳
1
⚁2
2007/04/01
3
2007/04/01
⚁ 明天飛日本
3
2007/04/01
⚁ 明天飛日本
⚁ 在YAPC::Asia要講兩場
3
2007/04/01
⚁ 明天飛日本
⚁ 在YAPC::Asia要講兩場
⚁ 糟:簡報還沒寫!
3
<@ij1iao>JIT流簡報
4
<@ij1iao>JIT流簡報
4
<@ij1iao>JIT流簡報
4
兩難
5
兩難
⚁ 有兩場演講
5
兩難
⚁ 有兩場演講
⚁ 要先做哪份簡報?
5
兩難
⚁ 有兩場演講
⚁ 要先做哪份簡報?
⚁ 糟:拿不定主意!
5
6
7
7
8
鬆了一口氣
9
鬆了一口氣
⚁ 坐等大家幫我下決定
9
鬆了一口氣
⚁ 坐等大家幫我下決定
⚁ 完全不急著準備簡報了
9
鬆了一口氣
⚁ 坐等大家幫我下決定
⚁ 完全不急著準備簡報了
⚁ 閒來無事,幫別人做決定吧!
9
Pick!
10
Pick!
“偽兩難”
10
Pick!
11
Pick!
11
Pick!
12
Pick!
12
Pick!
13
Pick!
13
Pick!
14
一小時過去了...
15
...開票!
16
♨17
Jifty
18
Jifty
♨網站應用程式框架
18
Jifty
♨網站應用程式框架♨簡單的事情=輕鬆完成
18
Jifty
♨網站應用程式框架♨簡單的事情=輕鬆完成
♨複雜的事情=輕鬆完成
18
Jifty=JFDI
19
Jifty=JFDI
♨ JustF*ckingDoIt
19
Jifty=JFDI
♨ JustF*ckingDoIt
♨讓大家JFDI
19
Jifty=JFDI
♨ JustF*ckingDoIt
♨讓大家JFDI
♨直接來寫Doxory!
19
20
•$cpan
20
•$cpan•cpan>notestinstallJifty
20
•$cpan•cpan>notestinstallJifty
“notest”可以省一小時的時間.
20
21
• $jiftyapp‐‐nameDoxory
21
• $jiftyapp‐‐nameDoxory• CreatingnewapplicationDoxory
CreatingdirectorylibCreatingdirectorylib/DoxoryCreatingdirectorybinCreatingdirectoryetcCreatingdirectorydocCreatingdirectorylogCreatingdirectoryvarCreatingdirectoryvar/masonCreatingdirectoryshareCreatingdirectoryshare/poCreatingdirectoryshare/webCreatingdirectoryshare/web/templatesCreatingdirectoryshare/web/staticCreatingdirectorylib/Doxory/ModelCreatingdirectorylib/Doxory/ActionCreatingdirectorytCreatingconfigurationfileDoxory/etc/config.yml
21
三份檔案
22
三份檔案
♨ bin/jifty
22
三份檔案
♨ bin/jifty
♨ etc/config.yml
22
三份檔案
♨ bin/jifty
♨ etc/config.yml
♨ Makefile.PL
22
23
• $jiftyserver
23
• $jiftyserver• INFO‐Youcanconnecttoyourserverat
http://localhost:8888/
23
動了!
24
動了!
這並不是Doxory.使用者(Users)在哪裡?
24
25
•$cdDoxory
25
•$cdDoxory
•$jiftymodel‐‐nameUser
25
•$cdDoxory
•$jiftymodel‐‐nameUser•Writingfilet/00‐model‐User.tWritingfilelib/Doxory/Model/User.pm
25
•$cdDoxory
•$jiftymodel‐‐nameUser•Writingfilet/00‐model‐User.tWritingfilelib/Doxory/Model/User.pm
•$vimlib/Doxory/Model/User.pm
25
• packageDoxory::Model::User;• useJifty::DBI::Schema;• • useDoxory::Recordschema{•
• • };
26
• packageDoxory::Model::User;• useJifty::DBI::Schema;• • useDoxory::Recordschema{• • columnname=>• labelis'Username',• hintsis'Otherpeopleseethiswhenyouaskquestions.',• isdistinct,• ismandatory;• • columnemail=>• labelis'Email',• hintsis'Wewillnotsellittoanybody.Honest.',• defaultis'',• isdistinct,• isimmutable;• • };
27
28
• $jiftyschema‐‐setup
28
• $jiftyschema‐‐setup• INFO‐GeneratingSQLforapplicationDoxory...
INFO‐UsingDoxory::Model::UserINFO‐UsingJifty::Model::SessionINFO‐UsingJifty::Model::MetadataINFO‐Setupversionv0.0.1,jiftyversion0.701170
28
• $jiftyschema‐‐setup• INFO‐GeneratingSQLforapplicationDoxory...
INFO‐UsingDoxory::Model::UserINFO‐UsingJifty::Model::SessionINFO‐UsingJifty::Model::MetadataINFO‐Setupversionv0.0.1,jiftyversion0.701170
•$jiftyserver&
28
• $jiftyschema‐‐setup• INFO‐GeneratingSQLforapplicationDoxory...
INFO‐UsingDoxory::Model::UserINFO‐UsingJifty::Model::SessionINFO‐UsingJifty::Model::MetadataINFO‐Setupversionv0.0.1,jiftyversion0.701170
•$jiftyserver&
• INFO‐Youcanconnecttoyourserverathttp://localhost:8888/
28
• $jiftyschema‐‐setup• INFO‐GeneratingSQLforapplicationDoxory...
INFO‐UsingDoxory::Model::UserINFO‐UsingJifty::Model::SessionINFO‐UsingJifty::Model::MetadataINFO‐Setupversionv0.0.1,jiftyversion0.701170
•$jiftyserver&
• INFO‐Youcanconnecttoyourserverathttp://localhost:8888/
• $openhttp://localhost:8888/
28
29
29
30
30
31
31
32
32
33
AudreyT
33
AudreyT
33
34
接著來寫選擇題(Choice)模型.
34
35
•$jiftymodel‐‐nameChoice
35
•$jiftymodel‐‐nameChoice•Writingfilet/00‐model‐Choice.tWritingfilelib/Doxory/Model/Choice.pm
35
•$jiftymodel‐‐nameChoice•Writingfilet/00‐model‐Choice.tWritingfilelib/Doxory/Model/Choice.pm
•$vimlib/Doxory/Model/Choice.pm
35
• packageDoxory::Model::Choice;• useJifty::DBI::Schema;• useDoxory::Recordschema{• • columnname=>• labelis'Ineedhelpdeciding...',• renderas'textarea';• • columna=>• labelis'Ontheonehand',• renderas'textarea',ismandatory;
• columnb=>• labelis'Ontheotherhand',• renderas'textarea',ismandatory;
• columnasked_by=>• labelis'Askedby',• defaultisdefer{Jifty‐>web‐>current_user‐>id},• referencesDoxory::Model::User;• • };
36
37
• $jiftyschema‐‐drop‐database‐‐setup
37
• $jiftyschema‐‐drop‐database‐‐setup• INFO‐GeneratingSQLforapplicationDoxory...
INFO‐UsingDoxory::Model::UserINFO‐UsingDoxory::Model::ChoiceINFO‐UsingJifty::Model::SessionINFO‐UsingJifty::Model::MetadataINFO‐Setupversionv0.0.1,jiftyversion0.701170
37
• $jiftyschema‐‐drop‐database‐‐setup• INFO‐GeneratingSQLforapplicationDoxory...
INFO‐UsingDoxory::Model::UserINFO‐UsingDoxory::Model::ChoiceINFO‐UsingJifty::Model::SessionINFO‐UsingJifty::Model::MetadataINFO‐Setupversionv0.0.1,jiftyversion0.701170
• $openhttp://localhost:8888/
37
38
38
39
39
40
40
41
41
42
42
43
做完了!...可是使用者要怎麼登入呢?
43
✍44
45
•$vimetc/config.yml
45
•$vimetc/config.yml
這裡要加兩列設定.
45
•‐‐‐•framework:•Plugins:•‐SkeletonApp:{}•‐REST:{}•‐Halo:{}•‐ErrorTemplates:{}•‐CompressedCSSandJS:{}••
•46
•‐‐‐•framework:•Plugins:•‐SkeletonApp:{}•‐REST:{}•‐Halo:{}•‐ErrorTemplates:{}•‐CompressedCSSandJS:{}•‐Authentication::Password:{}•SkipAccessControl:1
•47
•‐‐‐•framework:•Plugins:•‐SkeletonApp:{}•‐REST:{}•‐Halo:{}•‐ErrorTemplates:{}•‐CompressedCSSandJS:{}•‐Authentication::Password:{}•SkipAccessControl:1
• 懶得定義存取權限規則(ACL).
47
48
•$vimlib/Doxory/Model/User.pm
48
•$vimlib/Doxory/Model/User.pm
為User.pm加上兩個mixin.
48
• packageDoxory::Model::User;• useJifty::DBI::Schema;• useDoxory::Recordschema{• • columnname=>• labelis'Username',• hintsis'Otherpeopleseethiswhenyouaskquestions.',• isdistinct,• ismandatory;• • columnemail=>• labelis'Email',• hintsis'Wewillnotsellittoanybody.Honest.',• defaultis'',• isdistinct,• isimmutable;
• };
•49
• packageDoxory::Model::User;• useJifty::DBI::Schema;• useDoxory::Recordschema{• • columnname=>• labelis'Username',• hintsis'Otherpeopleseethiswhenyouaskquestions.',• isdistinct,• ismandatory;• • columnemail=>• labelis'Email',• hintsis'Wewillnotsellittoanybody.Honest.',• defaultis'',• isdistinct,• isimmutable;
• };
• useJifty::Plugin::User::Mixin::Model::User;• useJifty::Plugin::Authentication::Password::Mixin::Model::User;
50
51
51
52
52
53
From: Doxory <>Date: April 3, 2007 5:43:07 PM JSTTo: [email protected]: 歡迎光臨 Doxory!
您 (或自稱是您的某人) 在 Doxory 申請註冊新帳號.
請點擊以下鏈結, 以確認您的電郵位址:
http://127.0.0.1:8888/let/jesse%40bestpractical.com/confirm_email/78f28e934cf6c058
53
From: Doxory <>Date: April 3, 2007 5:43:07 PM JSTTo: [email protected]: 歡迎光臨 Doxory!
您 (或自稱是您的某人) 在 Doxory 申請註冊新帳號.
請點擊以下鏈結, 以確認您的電郵位址:
http://127.0.0.1:8888/let/jesse%40bestpractical.com/confirm_email/78f28e934cf6c058
53
54
54
55
登入成功了...(網頁界面呢?)
55
❁56
57
•$vimlib/Doxory/Dispatcher.pm
57
•$vimlib/Doxory/Dispatcher.pm
Dispatcher負責將網址對映到頁面(View).
57
58
• packageDoxory::Dispatcher;useJifty::Dispatcher‐base;
58
• packageDoxory::Dispatcher;useJifty::Dispatcher‐base;
•before'*'=>run{if(Jifty‐>web‐>current_user‐>id){
58
• packageDoxory::Dispatcher;useJifty::Dispatcher‐base;
•before'*'=>run{if(Jifty‐>web‐>current_user‐>id){
• my$top=Jifty‐>web‐>navigation;$top‐>child('Choices'=>url=>'/choices');
58
• packageDoxory::Dispatcher;useJifty::Dispatcher‐base;
•before'*'=>run{if(Jifty‐>web‐>current_user‐>id){
• my$top=Jifty‐>web‐>navigation;$top‐>child('Choices'=>url=>'/choices');
• }
58
• packageDoxory::Dispatcher;useJifty::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
• packageDoxory::Dispatcher;useJifty::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
• packageDoxory::Dispatcher;useJifty::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
59
接著來寫“/”頁面.
59
60
•$vimlib/Doxory/View.pm
60
•$vimlib/Doxory/View.pm
TT2退散!Mason退散!
♡
60
61
• packageDoxory::View;useJifty::View::Declare‐base;
61
• packageDoxory::View;useJifty::View::Declare‐base;
•template'/'=>page{h1{'Askaquestion!'}
61
• packageDoxory::View;useJifty::View::Declare‐base;
•template'/'=>page{h1{'Askaquestion!'}
• show'new_choice';
61
• packageDoxory::View;useJifty::View::Declare‐base;
•template'/'=>page{h1{'Askaquestion!'}
• show'new_choice';• };
61
• packageDoxory::View;useJifty::View::Declare‐base;
•template'/'=>page{h1{'Askaquestion!'}
• show'new_choice';• };
• privatetemplatenew_choice=>sub{div{form{
61
• packageDoxory::View;useJifty::View::Declare‐base;
•template'/'=>page{h1{'Askaquestion!'}
• show'new_choice';• };
• privatetemplatenew_choice=>sub{div{form{
• my$action=new_action(class=>'CreateChoice');
61
• packageDoxory::View;useJifty::View::Declare‐base;
•template'/'=>page{h1{'Askaquestion!'}
• show'new_choice';• };
• privatetemplatenew_choice=>sub{div{form{
• my$action=new_action(class=>'CreateChoice');• render_action($action=>['name','a','b']);
61
• packageDoxory::View;useJifty::View::Declare‐base;
•template'/'=>page{h1{'Askaquestion!'}
• show'new_choice';• };
• privatetemplatenew_choice=>sub{div{form{
• my$action=new_action(class=>'CreateChoice');• render_action($action=>['name','a','b']);• form_submit(label=>'AsktheCrowd!');
61
• packageDoxory::View;useJifty::View::Declare‐base;
•template'/'=>page{h1{'Askaquestion!'}
• show'new_choice';• };
• privatetemplatenew_choice=>sub{div{form{
• my$action=new_action(class=>'CreateChoice');• render_action($action=>['name','a','b']);• form_submit(label=>'AsktheCrowd!');• }}
61
• packageDoxory::View;useJifty::View::Declare‐base;
•template'/'=>page{h1{'Askaquestion!'}
• show'new_choice';• };
• privatetemplatenew_choice=>sub{div{form{
• my$action=new_action(class=>'CreateChoice');• render_action($action=>['name','a','b']);• form_submit(label=>'AsktheCrowd!');• }}• };
61
62
62
63
columna=>labelis'Ontheonehand',renderas'textarea',ismandatory;
63
64
64
65
然後輪到“choices”頁面.
65
•$vimlib/Doxory/View.pm
66
67
• packageDoxory::View;useJifty::View::Declare‐base;
67
• packageDoxory::View;useJifty::View::Declare‐base;
• template'/'=>page{...};privatetemplatenew_choice=>sub{...};
67
• packageDoxory::View;useJifty::View::Declare‐base;
• template'/'=>page{...};privatetemplatenew_choice=>sub{...};
• templatechoices=>page{
67
• packageDoxory::View;useJifty::View::Declare‐base;
• template'/'=>page{...};privatetemplatenew_choice=>sub{...};
• templatechoices=>page{• h1{'MyChoices'}
dl{
67
• packageDoxory::View;useJifty::View::Declare‐base;
• template'/'=>page{...};privatetemplatenew_choice=>sub{...};
• templatechoices=>page{• h1{'MyChoices'}
dl{• my$choices=Doxory::Model::ChoiceCollection‐>new;
$choices‐>limit(column=>'asked_by',value=>Jifty‐>web‐>current_user‐>id,);
67
• packageDoxory::View;useJifty::View::Declare‐base;
• template'/'=>page{...};privatetemplatenew_choice=>sub{...};
• templatechoices=>page{• h1{'MyChoices'}
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
68
等等...要怎麼投票啊?
68
☑69
70
•$jiftymodel‐‐nameVote
70
•$jiftymodel‐‐nameVote•Writingfilet/00‐model‐Vote.tWritingfilelib/Doxory/Model/Vote.pm
70
•$jiftymodel‐‐nameVote•Writingfilet/00‐model‐Vote.tWritingfilelib/Doxory/Model/Vote.pm
•$vimlib/Doxory/Model/Vote.pm
70
• packageDoxory::Model::Vote;• useJifty::DBI::Schema;
• useDoxory::Recordschema{• • columnchoice=>• referencesDoxory::Model::Choice;• • columnvoter=>• referencesDoxory::Model::User;
• columnsuggestion=>• validareqw(abskip);
• columncomments=>• labelis'Comments?',• renderas'textarea’;• • };
71
72
72
73
接著來寫“pick”頁面.
73
•$vimlib/Doxory/Dispatcher.pm
74
•$vimlib/Doxory/Dispatcher.pm
先將/pick加進導覽列.
74
• packageDoxory::Dispatcher;useJifty::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
• packageDoxory::Dispatcher;• ...• onpick=>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){• setchoice=>$c;• }• else{• show'nothing_to_pick';• }• };
76
• packageDoxory::Dispatcher;• ...• onpick=>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){• setchoice=>$c;• }• else{• show'nothing_to_pick';• }• };
“頭一道我還沒投票的選擇題”
76
•$vimlib/Doxory/View.pm
77
78
• packageDoxory::View;
78
• packageDoxory::View;• useJifty::View::Declare‐base;
template''=>page{...};privatetemplatechoices=>sub{...};
78
• packageDoxory::View;• useJifty::View::Declare‐base;
template''=>page{...};privatetemplatechoices=>sub{...};
• templatepick=>page{
78
• packageDoxory::View;• useJifty::View::Declare‐base;
template''=>page{...};privatetemplatechoices=>sub{...};
• templatepick=>page{• my$choice=get('choice');
78
• packageDoxory::View;• useJifty::View::Declare‐base;
template''=>page{...};privatetemplatechoices=>sub{...};
• templatepick=>page{• my$choice=get('choice');• my$action=new_action(class=>'CreateVote');
78
• packageDoxory::View;• useJifty::View::Declare‐base;
template''=>page{...};privatetemplatechoices=>sub{...};
• templatepick=>page{• my$choice=get('choice');• my$action=new_action(class=>'CreateVote');• my$redir=new_action(
class=>"Jifty::Action::Redirect",arguments=>{url=>'/pick'},);
78
• packageDoxory::View;• useJifty::View::Declare‐base;
template''=>page{...};privatetemplatechoices=>sub{...};
• templatepick=>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
• packageDoxory::View;• useJifty::View::Declare‐base;
template''=>page{...};privatetemplatechoices=>sub{...};
• templatepick=>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
• packageDoxory::View;• useJifty::View::Declare‐base;
template''=>page{...};privatetemplatechoices=>sub{...};
• templatepick=>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
• packageDoxory::View;• useJifty::View::Declare‐base;
template''=>page{...};privatetemplatechoices=>sub{...};
• templatepick=>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
• packageDoxory::View;• useJifty::View::Declare‐base;
template''=>page{...};privatetemplatechoices=>sub{...};
• templatepick=>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=>'Noneoftheabove',arguments=>{suggestion=>'skip',%args},);}
p{render_param($action=>'comments')}}}};
78
79
• packageDoxory::View;useJifty::View::Declare‐base;
template''=>page{...};privatetemplatenew_choice=>sub{...};templatechoices=>page{...};templatepick=>page{...};
79
• packageDoxory::View;useJifty::View::Declare‐base;
template''=>page{...};privatetemplatenew_choice=>sub{...};templatechoices=>page{...};templatepick=>page{...};
• templatenothing_to_pick=>page{h1{"There'snothingforyoutopick."}
79
• packageDoxory::View;useJifty::View::Declare‐base;
template''=>page{...};privatetemplatenew_choice=>sub{...};templatechoices=>page{...};templatepick=>page{...};
• templatenothing_to_pick=>page{h1{"There'snothingforyoutopick."}
•p{"Nooneyouknowisangstingaboutanything.Everybodyknowswherethey'regoingtodinner,whattodoontheirnextdateandwhethertodropthatclass.Youhavesuchlovelyandwelladjustedfriends."}
79
• packageDoxory::View;useJifty::View::Declare‐base;
template''=>page{...};privatetemplatenew_choice=>sub{...};templatechoices=>page{...};templatepick=>page{...};
• templatenothing_to_pick=>page{h1{"There'snothingforyoutopick."}
•p{"Nooneyouknowisangstingaboutanything.Everybodyknowswherethey'regoingtodinner,whattodoontheirnextdateandwhethertodropthatclass.Youhavesuchlovelyandwelladjustedfriends."}
• h2{"Maybeit'stimetoaskforsomeadvice..."};
79
• packageDoxory::View;useJifty::View::Declare‐base;
template''=>page{...};privatetemplatenew_choice=>sub{...};templatechoices=>page{...};templatepick=>page{...};
• templatenothing_to_pick=>page{h1{"There'snothingforyoutopick."}
•p{"Nooneyouknowisangstingaboutanything.Everybodyknowswherethey'regoingtodinner,whattodoontheirnextdateandwhethertodropthatclass.Youhavesuchlovelyandwelladjustedfriends."}
• h2{"Maybeit'stimetoaskforsomeadvice..."};
• show'new_choice';};
79
80
81
81
82
最後來改choices頁面,顯示目前統計的票數.
82
•$vimlib/Doxory/Model/Choice.pm
83
• packageDoxory::Model::Choice;• useJifty::DBI::Schema;• useDoxory::Recordschema{...}
• subin_favor_of_a{• my$self=shift;• $self‐>in_favor_of('a');• }
• subin_favor_of_b{• my$self=shift;• $self‐>in_favor_of('b');• }
• subin_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
•$vimlib/Doxory/View.pm
85
86
86
• packageDoxory::View;useJifty::View::Declare‐base;...
86
• packageDoxory::View;useJifty::View::Declare‐base;...
• templatechoices=>page{h1{'MyChoices'}
86
• packageDoxory::View;useJifty::View::Declare‐base;...
• templatechoices=>page{h1{'MyChoices'}
• dl{
86
• packageDoxory::View;useJifty::View::Declare‐base;...
• templatechoices=>page{h1{'MyChoices'}
• dl{• my$choices=Doxory::Model::ChoiceCollection‐>new;
$choices‐>limit(column=>'asked_by',value=>Jifty‐>web‐>current_user‐>id,);
86
• packageDoxory::View;useJifty::View::Declare‐base;...
• templatechoices=>page{h1{'MyChoices'}
• 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
• packageDoxory::View;useJifty::View::Declare‐base;...
• templatechoices=>page{h1{'MyChoices'}
• 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
• packageDoxory::View;useJifty::View::Declare‐base;...
• templatechoices=>page{h1{'MyChoices'}
• 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
• packageDoxory::View;useJifty::View::Declare‐base;...
• templatechoices=>page{h1{'MyChoices'}
• 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
• packageDoxory::View;useJifty::View::Declare‐base;...
• templatechoices=>page{h1{'MyChoices'}
• 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
87
隨堂練習:顯示投票時的留言.☺
87
大功告成!
88
大功告成!♨ lib/Doxory/Model/User.pm
88
大功告成!♨ lib/Doxory/Model/User.pm
♨ lib/Doxory/Model/Choice.pm
88
大功告成!♨ lib/Doxory/Model/User.pm
♨ lib/Doxory/Model/Choice.pm
♨ lib/Doxory/Model/Vote.pm
88
大功告成!♨ lib/Doxory/Model/User.pm
♨ lib/Doxory/Model/Choice.pm
♨ lib/Doxory/Model/Vote.pm
♨ lib/Doxory/Dispatcher.pm
88
大功告成!♨ lib/Doxory/Model/User.pm
♨ lib/Doxory/Model/Choice.pm
♨ lib/Doxory/Model/Vote.pm
♨ lib/Doxory/Dispatcher.pm
♨ lib/Doxory/View.pm
88
大功告成!♨ lib/Doxory/Model/User.pm
♨ lib/Doxory/Model/Choice.pm
♨ lib/Doxory/Model/Vote.pm
♨ lib/Doxory/Dispatcher.pm
♨ lib/Doxory/View.pm
88
☈89
網路分級
90
網路分級
☈ Doxory是普級網站
90
網路分級
☈ Doxory是普級網站
☈ 不能帶有色情暴力字樣
90
網路分級
☈ Doxory是普級網站
☈ 不能帶有色情暴力字樣☈ ...英文髒話也不行
90
Doxory言論管制
91
Doxory言論管制
☈ 沒問題!
91
Doxory言論管制
☈ 沒問題!
☈ 改一小段就行了
91
Doxory言論管制
☈ 沒問題!
☈ 改一小段就行了☈ vimlib/Doxory/Model/Choice.pm
91
92
• packageDoxory::Model::Choice;
92
• packageDoxory::Model::Choice;
• useRegexp::Common'profanity_us';
92
• packageDoxory::Model::Choice;
• useRegexp::Common'profanity_us';
• subvalidate_name{my($self,$name)=@_;
92
• packageDoxory::Model::Choice;
• useRegexp::Common'profanity_us';
• subvalidate_name{my($self,$name)=@_;
•if($name=~/$RE{profanity}/i){return(0,'Wouldyouspeaklikethat'.'infrontofyourmother?*cough*');}
92
• packageDoxory::Model::Choice;
• useRegexp::Common'profanity_us';
• subvalidate_name{my($self,$name)=@_;
•if($name=~/$RE{profanity}/i){return(0,'Wouldyouspeaklikethat'.'infrontofyourmother?*cough*');}
•return1;}
92
93
檢查器(Validator)
94
檢查器(Validator)
☈ 效果差強人意
94
檢查器(Validator)
☈ 效果差強人意☈ 使用者覺得要一直改很煩
94
檢查器(Validator)
☈ 效果差強人意☈ 使用者覺得要一直改很煩☈ 直接清乾淨就是了!
94
• packageDoxory::Model::Choice;useRegexp::Common'profanity_us';
• subcanonicalize_name{• my($self,$name)=@_;
• $name=~s/$RE{profanity}/**expletives**/gi;• return$name;• }
95
96
正規化(Canonicalizer)
97
正規化(Canonicalizer)
☈ 屬於Model的一部份
97
正規化(Canonicalizer)
☈ 屬於Model的一部份
☈ 自動補完(Autocompleter)亦同
97
正規化(Canonicalizer)
☈ 屬於Model的一部份
☈ 自動補完(Autocompleter)亦同
☈ 下一個題目:中文版Doxory
97
文98
•$vimlib/Doxory/Dispatcher.pm
99
•$vimlib/Doxory/Dispatcher.pm
先標明選單裡要國際化的字串.
99
• packageDoxory::Dispatcher;useJifty::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
• packageDoxory::Dispatcher;useJifty::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
•$vimlib/Doxory/Model/*.pm
102
•$vimlib/Doxory/Model/*.pm
再將各欄位的label,hints等標明.
102
• packageDoxory::Model::Choice;• useJifty::DBI::Schema;• useDoxory::Recordschema{• • columnname=>• labelis_('Ineedhelpdeciding...'),• renderas'textarea';• • columna=>• labelis_('Ontheonehand'),• renderas'textarea',ismandatory;
• columnb=>• labelis_('Ontheotherhand'),• renderas'textarea',ismandatory;
• columnasked_by=>• labelis_('Askedby'),• defaultisdefer{Jifty‐>web‐>current_user‐>id},• referencesDoxory::Model::User;• • };
103
• packageDoxory::Model::User;• useJifty::DBI::Schema;• • useDoxory::Recordschema{• • columnname=>
• labelis_('Username'),• hintsis_('Otherpeopleseethiswhenyouaskquestions.'),
• isdistinct,• ismandatory;• • columnemail=>
• labelis_('Email'),• hintsis_('Wewillnotsellittoanybody.Honest.'),
• defaultis'',• isdistinct,• isimmutable;• • };
104
• packageDoxory::Model::Vote;• useJifty::DBI::Schema;
• useDoxory::Recordschema{• • columnchoice=>• referencesDoxory::Model::Choice;• • columnvoter=>• referencesDoxory::Model::User;
• columnsuggestion=>• validareqw(abskip);
• columncomments=>• labelis_('Comments?'),• renderas'textarea’;• • };
105
•$vimlib/Doxory/View.pm
106
•$vimlib/Doxory/View.pm
最後再標明頁面裡要翻譯的部份.
106
• packageDoxory::View;useJifty::View::Declare‐base;
template'/'=>page{h1{_('Askaquestion!')}
• show'new_choice';• };
• privatetemplatenew_choice=>sub{div{form{
• my$action=new_action(class=>'CreateChoice');• render_action($action=>['name','a','b']);• form_submit(label=>_('AsktheCrowd!'));• }}• };
• ...
107
108
• $jiftypo‐‐languagezh_tw
108
• $jiftypo‐‐languagezh_tw
產生正體中文字典檔.
108
• $jiftypo‐‐languagezh_tw• INFO‐Extractingmessagesfrom'lib/Doxory/Dispatcher.pm'
INFO‐Extractingmessagesfrom'lib/Doxory/View.pm'INFO‐Extractingmessagesfrom'lib/Doxory/Model/Choice.pm'INFO‐Extractingmessagesfrom'lib/Doxory/Model/User.pm'INFO‐Extractingmessagesfrom'lib/Doxory/Model/Vote.pm'INFO‐Extractingmessagesfrom'bin/jifty'INFO‐Updatingmessagecatalog'share/po/zh_tw.po'
產生正體中文字典檔.
108
• $jiftypo‐‐languagezh_tw• INFO‐Extractingmessagesfrom'lib/Doxory/Dispatcher.pm'
INFO‐Extractingmessagesfrom'lib/Doxory/View.pm'INFO‐Extractingmessagesfrom'lib/Doxory/Model/Choice.pm'INFO‐Extractingmessagesfrom'lib/Doxory/Model/User.pm'INFO‐Extractingmessagesfrom'lib/Doxory/Model/Vote.pm'INFO‐Extractingmessagesfrom'bin/jifty'INFO‐Updatingmessagecatalog'share/po/zh_tw.po'
• $vimshare/po/zh_tw.po
產生正體中文字典檔.
108
• $jiftypo‐‐languagezh_tw• INFO‐Extractingmessagesfrom'lib/Doxory/Dispatcher.pm'
INFO‐Extractingmessagesfrom'lib/Doxory/View.pm'INFO‐Extractingmessagesfrom'lib/Doxory/Model/Choice.pm'INFO‐Extractingmessagesfrom'lib/Doxory/Model/User.pm'INFO‐Extractingmessagesfrom'lib/Doxory/Model/Vote.pm'INFO‐Extractingmessagesfrom'bin/jifty'INFO‐Updatingmessagecatalog'share/po/zh_tw.po'
• $vimshare/po/zh_tw.po
產生正體中文字典檔.
編輯正體中文字典檔.
108
• msgid""• msgstr""• "Content‐Type:text/plain;
charset=CHARSET\n"
• #:lib/Doxory/View.pm:8• msgid"Askaquestion!"• msgstr""
• #:lib/Doxory/View.pm:16• msgid"Askthecrowd!"• msgstr""
• #:lib/Doxory/Model/Choice.pm:23• msgid"Askedby"• msgstr""
• #:lib/Doxory/Dispatcher.pm:10• msgid"Choices"• msgstr""
• #:lib/Doxory/Model/Vote.pm:18• msgid"Comments?"• msgstr""
• #:lib/Doxory/Model/Choice.pm:9• msgid"Ineedhelpdeciding..."• msgstr""
• #:lib/Doxory/Model/Choice.pm:13• msgid"Ontheonehand"• msgstr""
• #:lib/Doxory/Model/Choice.pm:18• msgid"Ontheotherhand"• msgstr""
• #:lib/Doxory/Dispatcher.pm:9• msgid"Pick!"• msgstr""•
109
• msgid""• msgstr""• "Content‐Type:text/plain;
charset=UTF‐8\n"
• #:lib/Doxory/View.pm:8• msgid"Askaquestion!"• msgstr"我有問題!"
• #:lib/Doxory/View.pm:16• msgid"Askthecrowd!"• msgstr"聽聽鄉民怎麼說!"
• #:lib/Doxory/Model/Choice.pm:23• msgid"Askedby"• msgstr"提問人"
• #:lib/Doxory/Dispatcher.pm:10• msgid"Choices"• msgstr"開票紀錄"
• #:lib/Doxory/Model/Vote.pm:18• msgid"Comments?"• msgstr"有何指教?"
• #:lib/Doxory/Model/Choice.pm:9• msgid"Ineedhelpdeciding..."• msgstr"幫幫我,該怎麼辦..."
• #:lib/Doxory/Model/Choice.pm:13• msgid"Ontheonehand"• msgstr"我應該...?"
• #:lib/Doxory/Model/Choice.pm:18• msgid"Ontheotherhand"• msgstr"或者...?"
• #:lib/Doxory/Dispatcher.pm:9• msgid"Pick!"• msgstr"投票!"
•
110
111
现在译成简体中文看看...
111
112
• $b2g.pl‐p‐ushare/po/zh_tw.po>share/po/zh_cn.po
112
• $b2g.pl‐p‐ushare/po/zh_tw.po>share/po/zh_cn.po
先用Encode::HanConvert转成简体.
112
• $b2g.pl‐p‐ushare/po/zh_tw.po>share/po/zh_cn.po
• $vimetc/config.yml
先用Encode::HanConvert转成简体.
112
• $b2g.pl‐p‐ushare/po/zh_tw.po>share/po/zh_cn.po
• $vimetc/config.yml
先用Encode::HanConvert转成简体.
然后强制设定语系.
112
•‐‐‐•framework:•L10N:•PoDir:share/po
•113
•‐‐‐•framework:•L10N:•PoDir:share/po•Lang:zh‐cn
•114
115
国际化完成!
115
∀116
開發工具
117
開發工具
∀ 內建HTTP伺服器
117
開發工具
∀ 內建HTTP伺服器
∀ Module::Install
117
開發工具
∀ 內建HTTP伺服器
∀ Module::Install
∀ 自動生成PAR安裝套件
117
加持光輪(Halo)
118
加持光輪(Halo)
∀ 頁面顯示紀錄
118
加持光輪(Halo)
∀ 頁面顯示紀錄∀ 線上即時編輯
118
加持光輪(Halo)
∀ 頁面顯示紀錄∀ 線上即時編輯∀ ...還有更多更多!
118
Halo
119
Halo
∀ SQL查詢紀錄
119
Halo
∀ SQL查詢紀錄
∀ SQL效能分析
119
Halo
∀ SQL查詢紀錄
∀ SQL效能分析
∀ 頁面效能分析
119
Halo
∀ SQL查詢紀錄
∀ SQL效能分析
∀ 頁面效能分析
119
開發模式(DevelMode)
120
開發模式(DevelMode)
∀ Module::Refresh
120
開發模式(DevelMode)
∀ Module::Refresh
∀ Log4Perl事件紀錄
120
開發模式(DevelMode)
∀ Module::Refresh
∀ Log4Perl事件紀錄
∀ 線上管理界面
120
建置支援
121
建置支援
∀ Lighttpd/Apache
121
建置支援
∀ Lighttpd/Apache
∀ CSS::Squish壓縮器
121
建置支援
∀ Lighttpd/Apache
∀ CSS::Squish壓縮器
∀ JavaScript::Squish壓縮器
121
還有很多有趣的...
122
還有很多有趣的...
∀ 完善的I18N支援
122
還有很多有趣的...
∀ 完善的I18N支援
∀ 用戶端Session
122
還有很多有趣的...
∀ 完善的I18N支援
∀ 用戶端Session
∀ 事件(Event)訂閱
122
✈123
未來計劃
124
未來計劃
✈WikiUI線上互動編輯器
124
未來計劃
✈WikiUI線上互動編輯器
✈打更少字,做更多事
124
未來計劃
✈WikiUI線上互動編輯器
✈打更少字,做更多事
✈有聲書,教學光碟,MTV...
124
範例程式
125
範例程式
✈Wifty
125
範例程式
✈Wifty
✈ CommitBit
125
範例程式
✈Wifty
✈ CommitBit
✈ BabelBee
125
範例程式
✈Wifty
✈ CommitBit
✈ BabelBee
✈ Ping
125
範例程式
✈Wifty
✈ CommitBit
✈ BabelBee
✈ Ping
✈ Chat
125
範例程式
✈Wifty
✈ CommitBit
✈ BabelBee
✈ Ping
✈ Chat
✈ Clock
125
範例程式
✈Wifty
✈ CommitBit
✈ BabelBee
✈ Ping
✈ Chat
✈ Clock
✈ Doxory!
125
下載Jifty
126
下載Jifty
✈ cpanJifty
126
下載Jifty
✈ cpanJifty
✈ http://svn.jifty.org/svn/jifty.org
126
下載Jifty
✈ cpanJifty
✈ http://svn.jifty.org/svn/jifty.org
✈ http://jifty.org/
126
社群支援
127
社群支援
✈ Jifty::Manual::Tutorial
127
社群支援
✈ Jifty::Manual::Tutorial
✈ irc.freenode.net#jifty
127
fin.128
Bonus Slides(來不及譯成中文)
129
☺130
AnatomyofaJiftyApp
131
AnatomyofaJiftyApp
☺Model:Columns
131
AnatomyofaJiftyApp
☺Model:Columns
☺Action:Parameters
131
AnatomyofaJiftyApp
☺Model:Columns
☺Action:Parameters
☺ Template:Fragments
131
MoreComponents
132
MoreComponents
☺Dispatcher
132
MoreComponents
☺Dispatcher
☺ ClassLoader
132
MoreComponents
☺Dispatcher
☺ ClassLoader
☺ Continuations
132
䷗133
Jifty::DBI
134
Jifty::DBI
∅ CREATETABLE
134
Jifty::DBI
∅ CREATETABLE
∅ ALTERTABLE
134
Jifty::DBI
∅ CREATETABLE
∅ ALTERTABLE
∅ CREATEFOREIGNKEY
134
ObjectRelationalMapper
135
ObjectRelationalMapper
∅ SELECT
135
ObjectRelationalMapper
∅ SELECT
∅ INSERT
135
ObjectRelationalMapper
∅ SELECT
∅ INSERT
∅ UPDATE
135
ObjectRelationalMapper
∅ SELECT
∅ INSERT
∅ UPDATE
∅ DELETE
135
Jifty::DBI::Handle
136
Jifty::DBI::Handle
䷗SQLite
136
Jifty::DBI::Handle
䷗SQLite
䷗Postgres
136
Jifty::DBI::Handle
䷗SQLite
䷗Postgres
䷗MySQL
136
Jifty::DBI::Handle
䷗SQLite
䷗Postgres
䷗MySQL
䷗Oracle
136
Jifty::DBI::Collection
137
Jifty::DBI::Collection
䷗ JoinsandLimits
137
Jifty::DBI::Collection
䷗ JoinsandLimits
䷗ Paging=Data::Page
137
Jifty::DBI::Collection
䷗ JoinsandLimits
䷗ Paging=Data::Page
䷗ Caching=Memcached
137
Jifty::DBI::Schema
138
Jifty::DBI::Schema
䷗ DeclarativeColumns
138
Jifty::DBI::Schema
䷗ DeclarativeColumns
䷗ RememberourDoxory?
138
Jifty::DBI::Schema
䷗ DeclarativeColumns
䷗ RememberourDoxory?
䷗ Timefor0.0.2!
138
139
• packageDoxory::Model::Comment;useJifty::DBI::Schema;useDoxory::Recordschema{
since'0.0.2';
139
• packageDoxory::Model::Comment;useJifty::DBI::Schema;useDoxory::Recordschema{
since'0.0.2';•
columnUser=>referstoDoxory::Model:User;columnauthor=>referstoDoxory::Model::User;
139
• packageDoxory::Model::Comment;useJifty::DBI::Schema;useDoxory::Recordschema{
since'0.0.2';•
columnUser=>referstoDoxory::Model:User;columnauthor=>referstoDoxory::Model::User;
•columnbody=>labelis'Content',typeis'Text',renderas'Textarea',defaultis'FirstPost!';
139
• packageDoxory::Model::Comment;useJifty::DBI::Schema;useDoxory::Recordschema{
since'0.0.2';•
columnUser=>referstoDoxory::Model:User;columnauthor=>referstoDoxory::Model::User;
•columnbody=>labelis'Content',typeis'Text',renderas'Textarea',defaultis'FirstPost!';
•columntitle=>ismandatory,labelis'Title',lengthis40,hintsis'40bytesmax';
139
• packageDoxory::Model::Comment;useJifty::DBI::Schema;useDoxory::Recordschema{
since'0.0.2';•
columnUser=>referstoDoxory::Model:User;columnauthor=>referstoDoxory::Model::User;
•columnbody=>labelis'Content',typeis'Text',renderas'Textarea',defaultis'FirstPost!';
•columntitle=>ismandatory,labelis'Title',lengthis40,hintsis'40bytesmax';
•};
139
DatabaseUpgrade
140
DatabaseUpgrade
䷗ Usedtobepainful
140
DatabaseUpgrade
䷗ Usedtobepainful
䷗ Notanymore
140
DatabaseUpgrade
䷗ Usedtobepainful
䷗ Notanymore
䷗ Jiftyfixedit!
140
141
• $vimetc/config.yml
141
• $vimetc/config.yml• (Setversionto0.0.2)
141
• $vimetc/config.yml• (Setversionto0.0.2)
• $jiftyserver
141
• $vimetc/config.yml• (Setversionto0.0.2)
• $jiftyserver• Applicationschemaversionindatabase(v0.0.1)
doesn'tmatchapplicationschemaversion(0.0.2)Pleaserun`bin/jiftyschema‐‐setup`toupgradethedatabase.
141
• $vimetc/config.yml• (Setversionto0.0.2)
• $jiftyserver• Applicationschemaversionindatabase(v0.0.1)
doesn'tmatchapplicationschemaversion(0.0.2)Pleaserun`bin/jiftyschema‐‐setup`toupgradethedatabase.
•$jiftyschema‐‐setup
141
• $vimetc/config.yml• (Setversionto0.0.2)
• $jiftyserver• Applicationschemaversionindatabase(v0.0.1)
doesn'tmatchapplicationschemaversion(0.0.2)Pleaserun`bin/jiftyschema‐‐setup`toupgradethedatabase.
•$jiftyschema‐‐setup
• Jiftyversion0.605070uptodate.INFO‐GeneratingSQLtoupgradeDoxoryv0.0.1databasetov0.0.2INFO‐Upgradedtoversionv0.0.2
141
• $vimetc/config.yml• (Setversionto0.0.2)
• $jiftyserver• Applicationschemaversionindatabase(v0.0.1)
doesn'tmatchapplicationschemaversion(0.0.2)Pleaserun`bin/jiftyschema‐‐setup`toupgradethedatabase.
•$jiftyschema‐‐setup
• Jiftyversion0.605070uptodate.INFO‐GeneratingSQLtoupgradeDoxoryv0.0.1databasetov0.0.2INFO‐Upgradedtoversionv0.0.2
•$jiftyserver
141
• $vimetc/config.yml• (Setversionto0.0.2)
• $jiftyserver• Applicationschemaversionindatabase(v0.0.1)
doesn'tmatchapplicationschemaversion(0.0.2)Pleaserun`bin/jiftyschema‐‐setup`toupgradethedatabase.
•$jiftyschema‐‐setup
• Jiftyversion0.605070uptodate.INFO‐GeneratingSQLtoupgradeDoxoryv0.0.1databasetov0.0.2INFO‐Upgradedtoversionv0.0.2
•$jiftyserver
• INFO‐Youcanconnecttoyourserverathttp://localhost:8888/
141
142
• columntags=>since'0.0.3',referstoDoxory::Model::TagCollectionby'User';
142
• columntags=>since'0.0.3',referstoDoxory::Model::TagCollectionby'User';
•columnmood=>since'0.0.4',defaultis'happy',validare{display=>'Sad',value=>'sad'},{display=>'Happy',value=>'happy'};
142
• columntags=>since'0.0.3',referstoDoxory::Model::TagCollectionby'User';
•columnmood=>since'0.0.4',defaultis'happy',validare{display=>'Sad',value=>'sad'},{display=>'Happy',value=>'happy'};
•columncreated=>since'0.0.5',isimmutable,typeis'timestamp',defaultisliteral'now()',filtersare'Jifty::DBI::Filter::DateTime';
142
143
• $vimetc/config.yml
143
• $vimetc/config.yml• (Setversionto0.0.5)
143
• $vimetc/config.yml• (Setversionto0.0.5)•
$jiftyschema‐‐setup
143
• $vimetc/config.yml• (Setversionto0.0.5)•
$jiftyschema‐‐setup• Jiftyversion0.605070uptodate.
INFO‐GeneratingSQLtoupgradeDoxoryv0.0.2databasetov0.0.5INFO‐Upgradedtoversionv0.0.5
143
• $vimetc/config.yml• (Setversionto0.0.5)•
$jiftyschema‐‐setup• Jiftyversion0.605070uptodate.
INFO‐GeneratingSQLtoupgradeDoxoryv0.0.2databasetov0.0.5INFO‐Upgradedtoversionv0.0.5
•$jiftyserver
143
• $vimetc/config.yml• (Setversionto0.0.5)•
$jiftyschema‐‐setup• Jiftyversion0.605070uptodate.
INFO‐GeneratingSQLtoupgradeDoxoryv0.0.2databasetov0.0.5INFO‐Upgradedtoversionv0.0.5
•$jiftyserver
• INFO‐Youcanconnecttoyourserverathttp://localhost:8888/
143
⇛144
Action=APIs
145
Action=APIs
⇛ MethodCalls
145
Action=APIs
⇛ MethodCalls
⇛ Typednamedarguments
145
Action=APIs
⇛ MethodCalls
⇛ Typednamedarguments
⇛ Returnsresultsorerrors
145
Action≠URLs
146
Action≠URLs
⇛ Manyactionsononepage
146
Action≠URLs
⇛ Manyactionsononepage
⇛ Calledwithwebforms
146
Action≠URLs
⇛ Manyactionsononepage
⇛ Calledwithwebforms
⇛ SoundslikeRPC?
146
Action=RPC
147
Action=RPC
⇛ Webformencoding
147
Action=RPC
⇛ Webformencoding
⇛ XML/YAMLencoding
147
Action=RPC
⇛ Webformencoding
⇛ XML/YAMLencoding
⇛ Webservicesforfree!
147
Model⇛Action
148
Model⇛Action⇛ Doxory::Action::CreateUser
148
Model⇛Action⇛ Doxory::Action::CreateUser
⇛ Doxory::Action::SearchUser
148
Model⇛Action⇛ Doxory::Action::CreateUser
⇛ Doxory::Action::SearchUser
⇛ Doxory::Action::UpdateUser
148
Model⇛Action⇛ Doxory::Action::CreateUser
⇛ Doxory::Action::SearchUser
⇛ Doxory::Action::UpdateUser
⇛ Doxory::Action::DeleteUser
148
MakeyourownActions
149
150
• packageHello::Action::SayHi;useJifty::Param::Schema;useJifty::Actionschema{paramname=>labelis'Yourname?';};
150
• packageHello::Action::SayHi;useJifty::Param::Schema;useJifty::Actionschema{paramname=>labelis'Yourname?';};
•subtake_action{my$self=shift;my$name=$self‐>argument_value('name');$self‐>result‐>message("Hello,$name");}
150
151
• <%init>my$action=Jifty‐>web‐>new_action(class=>'SayHi');</%init>
151
• <%init>my$action=Jifty‐>web‐>new_action(class=>'SayHi');</%init>
•<&|/_elements/wrapper&><%Jifty‐>web‐>form‐>start%><%$action‐>form_field('name')%><%Jifty‐>web‐>form‐>submit%><%Jifty‐>web‐>form‐>end%></&>
151
• <%init>my$action=Jifty‐>web‐>new_action(class=>'SayHi');</%init>
•<&|/_elements/wrapper&><%Jifty‐>web‐>form‐>start%><%$action‐>form_field('name')%><%Jifty‐>web‐>form‐>submit%><%Jifty‐>web‐>form‐>end%></&>
151
• <%init>my$action=Jifty‐>web‐>new_action(class=>'SayHi');</%init>
•<&|/_elements/wrapper&><%Jifty‐>web‐>form‐>start%><%$action‐>form_field('name')%><%Jifty‐>web‐>form‐>submit%><%Jifty‐>web‐>form‐>end%></&>
151
152
• $curl\http://localhost:8888/__jifty/webservices/yaml?\J:A‐1=SayHi;J:A:F‐name‐1=Jesse
152
• $curl\http://localhost:8888/__jifty/webservices/yaml?\J:A‐1=SayHi;J:A:F‐name‐1=Jesse
•1:!!perl/hash:Jifty::Result_content:{}action_class:Hello::Action::SayHifailure:0field_errors:name:~field_warnings:name:~message:'Hello,Jesse'
152
☸153
Jifty::Dispatcher
154
Dispatcher=Kernel
155
Dispatcher=Kernel
☸ Simple
155
Dispatcher=Kernel
☸ Simple
☸ Declarative
155
Dispatcher=Kernel
☸ Simple
☸ Declarative
☸ Encapsulatesviewlogic
155
ThreeStages
156
ThreeStages
☸ Before:Setsupstate
156
ThreeStages
☸ Before:Setsupstate
☸ On:Showsyourpages
156
ThreeStages
☸ Before:Setsupstate
☸ On:Showsyourpages
☸ After:Cleansupstate
156
Jifty::ClassLoader
157
ScaffoldingBad
158
ScaffoldingBad
☸ Ugly
158
ScaffoldingBad
☸ Ugly
☸ Redundant
158
ScaffoldingBad
☸ Ugly
☸ Redundant
☸ Fragile
158
ScaffoldingBad
☸ Ugly
☸ Redundant
☸ Fragile
☸ Annoying
158
ScaffoldingBad
☸ Ugly
☸ Redundant
☸ Fragile
☸ Annoying
☸ Redundant
158
ScaffoldingBad
☸ Ugly
☸ Redundant
☸ Fragile
☸ Annoying
☸ Redundant
☸ Redundant
158
WhyEmptyClasses?
159
WhyEmptyClasses?
☸ Jifty::ClassLoader
159
WhyEmptyClasses?
☸ Jifty::ClassLoader
☸ Auto‐createsclasses
159
WhyEmptyClasses?
☸ Jifty::ClassLoader
☸ Auto‐createsclasses
☸ Neverwritesthemtodisk
159
Auto‐createdClasses
160
Auto‐createdClasses☸ Doxory
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection☸ Doxory::Bootstrap
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection☸ Doxory::Bootstrap☸ Doxory::Upgrade
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection☸ Doxory::Bootstrap☸ Doxory::Upgrade☸ Doxory::Dispatcher
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection☸ Doxory::Bootstrap☸ Doxory::Upgrade☸ Doxory::Dispatcher☸ Doxory::CurrentUser
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection☸ Doxory::Bootstrap☸ Doxory::Upgrade☸ Doxory::Dispatcher☸ Doxory::CurrentUser
☸ Doxory::Model::UserCollection
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection☸ Doxory::Bootstrap☸ Doxory::Upgrade☸ Doxory::Dispatcher☸ Doxory::CurrentUser
☸ Doxory::Model::UserCollection
☸ Doxory::Action::CreateUser
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection☸ Doxory::Bootstrap☸ Doxory::Upgrade☸ Doxory::Dispatcher☸ Doxory::CurrentUser
☸ Doxory::Model::UserCollection
☸ Doxory::Action::CreateUser☸ Doxory::Action::SearchUser
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection☸ Doxory::Bootstrap☸ Doxory::Upgrade☸ Doxory::Dispatcher☸ Doxory::CurrentUser
☸ Doxory::Model::UserCollection
☸ Doxory::Action::CreateUser☸ Doxory::Action::SearchUser☸ Doxory::Action::UpdateUser
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection☸ Doxory::Bootstrap☸ Doxory::Upgrade☸ Doxory::Dispatcher☸ Doxory::CurrentUser
☸ Doxory::Model::UserCollection
☸ Doxory::Action::CreateUser☸ Doxory::Action::SearchUser☸ Doxory::Action::UpdateUser☸ Doxory::Action::DeleteUser
160
Auto‐createdClasses☸ Doxory☸ Doxory::Record☸ Doxory::Collection☸ Doxory::Bootstrap☸ Doxory::Upgrade☸ Doxory::Dispatcher☸ Doxory::CurrentUser
☸ Doxory::Model::UserCollection
☸ Doxory::Action::CreateUser☸ Doxory::Action::SearchUser☸ Doxory::Action::UpdateUser☸ Doxory::Action::DeleteUser☸ ...etcetera
160
☯161
Continuation=JobControl
162
Continuation=JobControl
☯ ContinuationsinPerl?
162
Continuation=JobControl
☯ ContinuationsinPerl?
☯ NotFullContinuations
162
Continuation=JobControl
☯ ContinuationsinPerl?
☯ NotFullContinuations
☯ DelimitedContinuations
162
FullContinuations
163
FullContinuations
☯ Serializeseverything
163
FullContinuations
☯ Serializeseverything
☯ %ENV,STDIN,STDOUT
163
FullContinuations
☯ Serializeseverything
☯ %ENV,STDIN,STDOUT
☯ DBIHandle,LogHandle
163
FullContinuations
☯ Serializeseverything
☯ %ENV,STDIN,STDOUT
☯ DBIHandle,LogHandle
☯ Phaseofthemoon
163
JiftyContinuations
164
JiftyContinuations
☯ Onlytheapplicationstate
164
JiftyContinuations
☯ Onlytheapplicationstate
☯ RequestsandActions
164
JiftyContinuations
☯ Onlytheapplicationstate
☯ RequestsandActions
☯ That’sallweneed
164
WhyContinuations?
165
WhyContinuations?
☯ ThewebisbuiltonGOTO
165
WhyContinuations?
☯ ThewebisbuiltonGOTO
☯ DoyoulikeGOTO?
165
WhyContinuations?
☯ ThewebisbuiltonGOTO
☯ DoyoulikeGOTO?
☯ ContinuationsareGOSUB
165
WhyContinuations?
☯ ThewebisbuiltonGOTO
☯ DoyoulikeGOTO?
☯ ContinuationsareGOSUB
☯ WelcometoCivilization!
165
❀166
Templates=View
167
Templates=View
❀ Template::Declare
167
Templates=View
❀ Template::Declare
❀ HTML::Mason
167
Templates=View
❀ Template::Declare
❀ HTML::Mason
❀MasonhasComponents
167
Templates=View
❀ Template::Declare
❀ HTML::Mason
❀MasonhasComponents
❀ Server‐sideinclusion
167
Fragments
168
Fragments
❀ Components2.0
168
Fragments
❀ Components2.0
❀ Client‐sideforAJAX
168
Fragments
❀ Components2.0
❀ Client‐sideforAJAX
❀ Server‐sideforLynx
168
• <%Jifty‐>web‐>region(• name=>"myweDoxory‐posts",• path=>"/fragments/page_of_posts"• )%>
169
Chat
170
Chat
❀ Server‐push(Comet)
170
Chat
❀ Server‐push(Comet)
❀ Refreshedfragments
170
Chat
❀ Server‐push(Comet)
❀ Refreshedfragments
❀ LiveDemo!
170
!ank y"!♨
171