Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mojoliciousでつくる! Webアプリ入門

Mojoliciousでつくる! Webアプリ入門

2013/09/21
YAPC::Asia 2013
Yusuke Wada a.k.a. yusukebe

Yusuke Wada

May 07, 2023
Tweet

More Decks by Yusuke Wada

Other Decks in Programming

Transcript

  1. .PKPMJDJPVTͰͭ͘Δʂ
    8FCΞϓϦೖ໳

    :"1$"TJB
    :VTVLF8BEBBLBZVTVLFCF
    Some papix photos are in this slides. Thanks to papix!

    View Slide

  2. ΠϯτϩμΫγϣϯ

    View Slide

  3. ࣗݾ঺հ
    w ࿨ా༟հੜ
    w ܚጯٛक़େ੍ֶ࡞ϝσΟΞݚڀՊमྃ
    w גࣜձࣾϫσΟοτ୅දऔక໾
    w גࣜձࣾΦϞϩΩऔక໾݉࠷ߴٕज़੹೚ऀ
    w IUUQZVTVLFCFDPNPS!ZVTVLFCF

    View Slide

  4. ϝΠϯϫʔΫ

    View Slide

  5. ໰͍͔͚

    View Slide

  6. 1FSM͸େن໛8FCαʔϏε
    Ͱ࢖ΘΕ͍ͯΔ͕
    ॳ৺ऀ͕8FCΞϓϦʹೖ໳͢Δࢿྉ͕গͳ͍ʁ

    View Slide

  7. ͋͑ͯڈ೥ΛৼΓฦΔ
    ʮ৽͍͠ʯΛੜΈग़ͨ͢Ίͷ8FCΞϓϦ։ൃͱͦͷपล

    View Slide

  8. ԿΛͭ͘Δ͔͸෼͔ͬͨ
    ͦͷͨΊͷ
    ࣮૷ʹ͍ͭͯ
    ຊ೔ͷओ୊

    View Slide

  9. ର৅ΦʔσΟΤϯε
    w 8FCΞϓϦέʔγϣϯΛͭ͘Γ͍ͨํ
    w ΞΠσΞ͸͋Δ͕࣮૷Ͱ͖ͳ͍ͬͯํ
    w ࠷ۙͷ8"'ʹ͍ͭͯ஌Γ͍ͨํ
    w 8FC"QQMJDBUJPO'SBNFXPSL8"'
    w .PKPMJDJPVTΛ࢖ͬͨ۩ମతͳΞϓϦߏ੒Λ
    ஌Γ͍ͨํ

    View Slide

  10. ํ਑
    ౰ͨΓલʹ࢖͍ͬͯΔ֓೦ɺ࣮૷ɺΩʔϫʔυ
    טΈࡅ͍ͯղઆ
    (PPHMF΍$1"/ͰݕࡧͰ͖ΔΑ͏ʹʂ
    ࣮͸͘͢͝पล͔Β͸෼͔Γʹ͍͘ʁ

    View Slide

  11. ΞδΣϯμ
    w ྫ୊ɿ઎͍ΞϓϦʹ͍ͭͯ
    w 8FCΞϓϦέʔγϣϯͱ'SBNFXPSL
    w .PKPMJDJPVTͷ঺հ
    w .PKPMJDJPVT-JUFΛ࢖͏
    w ΑΓ࣮ફతͳΞϓϦ΁
    w $1"/Ϟδϡʔϧͱͷ૊Έ߹Θͤͱ޻෉
    w ࠓޙ΁

    View Slide

  12. ྫ୊ɿ઎͍ΞϓϦʹ͍ͭͯ

    View Slide

  13. ໊લʹԠͯ͡઎͍݁ՌΛग़͢
    w ઎͍݁Ռ͸·ͣछྨ
    w ྑ͍ࣄ͕ى͜ΔͰ͠ΐ͏
    w ग़ձ͍͕͋Δ͔΋ʁ
    w ෆ޾ʹͳΓ·͢
    w ೖྗ͞Ε໊ͨલʹରͯ͠ඞͣಉ݁͡Ռ
    w ZVTVLFCFʮग़ձ͍͕͋Δ͔΋ʁʯ

    View Slide

  14. ϋογϡؔ਺
    my $name = "yusukebe";
    my $max = 3;
    my $number = 0;
    # จࣈྻΛҰจࣈͣͭ෼ղ
    for my $char (split //, $name) {
    # จࣈʹରԠ͢Δ਺஋ΛಘΔ
    $number += ord $char;
    }
    # ૝ఆ͞ΕΔ࠷େ஋Ͱׂͬͨ༨ΓΛಘΔ
    my $result = $number % $max;
    print "$result\n";
    จࣈྻ
    ਺஋
    ݻఆ஋ͰׂΔ
    ༨Γ͕݁Ռ

    View Slide

  15. εΫϦϓτͰ࣮ݱ͢Δ
    Α͏͸਍அϝ˓ΧʔΈ͍ͨͳʁ

    View Slide

  16. 8FCΞϓϦέʔγϣϯͱ'SBNFXPSL

    View Slide

  17. 8FCΞϓϦέʔγϣϯΛఆٛ͢Δ
    8FC͕୭͔ͱಛ௃తͳ
    ΠϯλϥΫγϣϯ
    Λ͢Δ৔߹
    8FCΞϓϦέʔγϣϯ

    View Slide

  18. 8FCͷΠϯλϥΫγϣϯ
    8FC
    ΞϓϦέʔγϣϯ
    Ϣʔβʔ
    ྫ͑͹ࣗ෼ͷ໊લΛ
    ೖྗ͢Δ
    ઎͍ͷ݁ՌΛݟΔ
    +4ͷಈ࡞
    ֎෦ͷ8FC"1*
    ϛυϧ΢ΣΞFUD
    ϒϥ΢β
    ϓϩάϥϜ
    εϚϗΞϓϦ

    View Slide

  19. 8FC"QQMJDBUJPO'SBNFXPSL
    w ௨শ8"'ʢϫοϑʣ
    w ྫ͑͹3VCZPO3BJMT
    w 8FCΞϓϦέʔγϣϯΛͭ͘ΔͨΊͷ౔୆
    w .7$Ϟσϧʹجͮ͘৔߹͕ଟ͍
    .7$ͬͯͳΜͧʔʁ

    View Slide

  20. .PEFM
    7JFX
    $POUSPMMFS
    .7$
    .7$Ͱ͋Δҙຯ͸ʁ

    View Slide

  21. .7$Ҏલ

    View Slide

  22. Կ͕Πέͯͳ͍ͬͯʁ
    w ৭ʑࠞͬͯ͡Δ
    w ϔομʔग़ྗ
    w ϩδοΫॲཧ
    w )5.-ͷඳը
    w ϑΝΠϧ͝ͱʹϧʔςΟϯά͢Δ
    w ॏෳ͕ى͜Δ
    ˎ$(*͸σϓϩΠํ๏ͷ
    ҰͭͳͷͰ$(*ࣗମ͕
    ྑ͘ͳ͍Θ͚Ͱ͸ͳ͍

    View Slide

  23. ۪௚ʹDHJΛॻ͘ͱ
    use CGI qw/param header/;
    my $name = param('name');
    my @list = qw/ྑ͍ࣄ͕ى͜ΔͰ͠ΐ͏ ग़ձ͍͕͋Δ͔΋ʁ ෆ޾ʹͳΓ·͢/;
    my $num = 0;
    $num += ord ($_) for split //, $name;
    my $index = $num % scalar @list;
    my $message = $list[$index];
    print header('text/html; charset=utf-8');
    print "";
    print "$message";
    print "";

    View Slide

  24. )5.-͚ͩͰ΋෼཭ͤ͞Δͱ
    use CGI qw/param header/;
    use Text::MicroTemplate qw/render_mt/;
    use Data::Section::Simple qw/get_data_section/;
    my $name = param('name');
    my @list = qw/ྑ͍ࣄ͕ى͜ΔͰ͠ΐ͏ ग़ձ͍͕͋Δ͔΋ʁ ෆ޾ʹͳΓ·͢/;
    my $num = 0; $num += ord ($_) for split //, $name;
    my $index = $num % scalar @list;
    my $message = $list[$index];
    my $template = get_data_section('index.mt');
    my $html = render_mt($template, $message)->as_string();
    print header('text/html; charset=utf-8');
    print $html;
    __DATA__
    @@ index.mt


    = $_[0] ?>


    View Slide

  25. ৑௕ʹͳΔ͕
    ݟ௨͕͠Α͘ͳΔʂ
    ͞ΒʹςϯϓϨʔτΛϑΝΠϧʹ෼͚Δͱ
    ϝϯςφϯεੑɺ࠶ར༻ੑͷ޲্
    ৑௕ੑ͸ϑϨʔϜϫʔΫ͕ٵऩͯ͘͠ΕΔʁ

    View Slide

  26. ͱΓ͋͑ͣ.7$Ͱߟ͑Δҙຯ
    w ࠞࡏ͍ͯ͠Δݻ·ΓΛ໾ׂͰ෼͚Δ
    w ཧղΛ͢Ε͹৑௕ʹͳΔ͕։ൃޮ཰্͕͕Δ

    View Slide

  27. ෼͚Δͱ͸෼͔Δ͜ͱ

    View Slide

  28. ੾Γ෼͚ํ
    3PVUFS
    $POUSPMMFS
    .PEFM-PHJD
    %#૚03.BQQFS
    7JFX4UBUJDpMFT
    ϏδωεϩδοΫΛѻ͏
    ग़ྗ΍ݟͨ໨ʹؔ͢Δ෦෼
    ݸผͷϦΫΤετʹجͮ͘ॲཧ
    σʔλϕʔεʹ·ͭΘΔ
    63-.&5)0%ʹԠͯ͡ৼΓ෼͚Δ

    View Slide

  29. ໾ׂΛ෼͚Δ͜ͱ

    ϑϨʔϜϫʔΫతࢥߟ΁

    View Slide

  30. ॲཧͷྲྀΕ
    3PVUFS
    $POUSPMMFS
    .PEFM-PHJD
    %#03.BQQFS
    7JFX
    ϦΫΤετ
    σΟεύον
    Ϟσϧݺͼग़͠
    %#ݺͼग़͠ %#݁Ռฦ٫
    ݁Ռ
    ϨϯμϦϯά
    )5.-ͳͲ
    Ϩεϙϯε

    View Slide

  31. 1FSMͷ8"'ୡ
    w $BUBMZTU
    w %BODFS
    w "NPO
    w ,PTTZ
    w 1JDLMFT
    w 7PTPO
    w .PKPMJDJPVT
    w ࣗ࡞8"'

    View Slide

  32. ࣗ࡞8"'ͱطଘ8"'
    w .7$ʁΛ࣮ݱ͢ΔϞδϡʔϧ͸ଗ͍ͬͯΔ
    w 1MBDL3FRVFTU
    w 3PVUFS4JNQMF
    w 5FYU9TMBUF
    w ͨͩΞϓϦΛॻ͖ͳ͕Β8"'΋͸Ωπ͍
    w ษڧ༻ʹंྠͷ࠶ൃ໌͸ଟ͍ʹ׻ܴ
    w Ͱ΋ͱΓ͋͑ͣ8"'Λ࢖͍·͠ΐ͏Ͷ—

    View Slide

  33. .PKPMJDJPVTͷ঺հ

    View Slide

  34. .PKPMJDJPVT
    w ଐʹݴ͏ʮܰྔ8"'ʯͷҰछ
    w ࠷৽7FS͸ʮʯ೥݄೔࣌఺
    w ࡞ऀ͸ʮ4FCBTUJBO3JFEFMʯࢯ

    View Slide

  35. ಛ௃7$͚ͩαϙʔτ
    w 3PVUJOH$POUSPMMFS
    w σϑΥϧτͰ͸.PKP5FNQMBUFΛ࢖͏7JFX
    w ͷΈαϙʔτ͠ʮ.PEFMʯ͸ର৅֎
    .PKP#BTFͦͷଞͰΫϥεͭͬͨ͘Γ03.BQQFS
    ࢖ͬͨΓͯࣗ͠ྗͰ࣮૷ͯ͠Ͷ͍̇ͬͯ͏
    ٯʹͦΕ͕͍͍
    .PEFM-PHJD૚͸8FC͔Β੾Γ཭͢΂͖

    View Slide

  36. ಛ௃/PUGVMMTUBDLCVUGVMMTUBDL
    3VCZPO3BJMT
    %#Λѻ͏·Ͱશͯ͜ΕҰͭͰग़དྷΔ ϑϧελοΫ
    .PKPMJDJPVT
    )551ͷ3FRVFTU΍6TFS"HFOU·Ͱ
    .PKPMJDJPVTͰ࢖͏ϥΠϒϥϦ͕શͯࣗ࡞
    ϑϧελοΫ
    ίΞҎ֎ͷ$1"/Ϟδϡʔϧʹґଘ͠ͳ͍ʂ

    View Slide

  37. View Slide

  38. DQBON.PKPMJDJPVT

    View Slide

  39. .PKPMJDJPVTͳΒҰൃ

    View Slide

  40. ಛ௃ͦͷଞ
    w Ξοϓσʔτ͕සൟ
    $self->render_json( $ref ); # 4.00 Ͱഇࢭ
    # =>
    $self->render( json => $ref );
    ͨͩ͠ґଘ͕ແ͍ͷͰ.PKPMJDJPVT͚ͩ௥͍ͬͯΕ͹Α͍
    w .PKPMJDJPVT-JUFΛ࢖͑͹ϑΝΠϧҰͭͰ
    w ޻෉͢Ε͹$(*Ͱ΋ಈ࡞Մೳ
    w 1FSMҎ্ඞਢɺҎ্Λਪ঑
    w ։ൃ༻αʔόNPSCPɺຊ൪༻IZQOPUPBE
    w ΋ͪΖΜ14(*ޓ׵

    View Slide

  41. খ͞ͳΞϓϦ͔Βେ͖ͳ8FCΞϓϦ·Ͱ
    ঃʑʹֶ΂ΔϑϨʔϜϫʔΫ
    .PKPMJDJPVT-JUF
    .PKPMJDJPVT
    $1"/Ϟδϡʔϧͷ૊Έ߹Θͤ

    View Slide

  42. .PKPMJDJPVT-JUFΛ࢖͏

    View Slide

  43. NPKPίϚϯυʹΑΔεέϧτϯ
    $ mojo generate lite_app myapp.pl
    .PKPMJDJPVT-JUF

    View Slide

  44. ͸͡Ίͯͷ.PKPMJDJPVT-JUF
    #!/usr/bin/env perl
    use Mojolicious::Lite;
    get '/' => sub {
    my $self = shift;
    $self->stash->{message} = 'Hello Mojo!';
    $self->render('index');
    };
    app->start;
    __DATA__
    @@ index.html.ep


    <%= $message %>


    $POUSPMMFSʹ֘౰
    7JFXʢςϯϓϨʔτʣ
    3PVUJOHͯ͠Δ

    View Slide

  45. ্ཱͪ͛ํ
    $ morbo -l "http://*:5000" myapp.pl
    NPSCPΛ࢖͏
    $ plackup -p 5000 myapp.pl
    QMBDLVQͰ্ཱͪ͛Δ

    View Slide

  46. )FMMP8PSME͔ΒֶͿ
    get '/' => sub {};
    ϧʔςΟϯάͱίϯτϩʔϥ
    (&5IUUQMPDBMIPTU
    get '/entry/:id' => sub {
    my $entry_id = $self->stash->{id};
    };
    post '/entry' => sub {};
    1045IUUQMPDBMIPTUFOUSZ
    (&5IUUQMPDBMIPTUFOUSZ

    View Slide

  47. )FMMP8PSME͔ΒֶͿ
    get '/' => sub {
    my $self = shift;
    $self->stash->{message} = 'Hello Mojo';
    ...;
    }
    ςϯϓϨʔτʹσʔλΛ౉͢
    $self->render('index'); # index.html.ep Λඳը
    ...;
    <%= $message %>
    ςϯϓϨʔτͷهड़ͱϨϯμʔ

    View Slide

  48. ΋ͪΖΜ઎͍ΞϓϦ΋ʂ

    View Slide

  49. 4IPSUMJWFDPEJOH

    View Slide

  50. #!/usr/bin/env perl
    use Mojolicious::Lite;
    use utf8;
    ...;
    get '/' => sub {
    my $self = shift;
    $self->render('index');
    };
    ...;
    @@ index.html.ep
    ໊લΛೖྗ͍ͯͩ͘͠͞




    τοϓϖʔδΛඳը

    View Slide

  51. ...;
    get '/result' => sub {
    my $self = shift;
    my $name = $self->req->param('name');
    my @list
    = qw/ྑ͍ࣄ͕ى͜ΔͰ͠ΐ͏ ग़ձ͍͕͋Δ͔΋ʁ ෆ޾ʹͳΓ·͢/;
    my $num = 0;
    $num += ord ($_) for split //, $name;
    my $index = $num % scalar @list;
    $self->stash->{message} = $list[$index];
    $self->stash->{name} = $name;
    $self->render('result');
    };
    ...;
    @@ result.html.ep
    <%= $name %>͞Μͷ݁Ռʮ<%= $message %>ʯ
    ݁ՌΛग़ྗ

    View Slide

  52. $POUSPMMFS಺Ͱͷૢ࡞
    w શͯ͸ʮTFMGʯͷϝιουΛѻ͏
    my $value = $self->req->param('key');
    $self->render('entry');
    $self->render( json => { key => $value } );
    .PKPMJDJPVT$POUSPMMFSΛܧঝ͢ΔͷͰͦͷυΩϡϝϯτΛಡΊ͹0,ʂ
    $self->redirect_to('/');

    View Slide

  53. .PKP5FNQMBUFपΓ
    w 1FSMJTIUFNQMBUFT1FSMॻ͚Δʂ
    % for my $entry (@$entries) {
    <%= $entry->{title} %>
    % }
    .PKP5FNQMBUF.PKPMJDJPVT1MVHJO%FGBVMU)FMQFS
    w ςϯϓϨʔτ޲͚IFMQFS
    @@ index.html.ep
    % layout 'default';
    Hi, <%= $name %>
    @@ layouts/default.html.ep

    <%= content %>

    View Slide

  54. .PKPMJDJPVT-JUFΞϓϦΛ֦ு͢Δ
    w QVCMJD੩తϑΝΠϧΛஔ͘
    w UFNQMBUFTςϯϓϨʔτϑΝΠϧΛಠཱ
    ./
    !"" myapp.pl
    !"" public/
    # !"" css/
    # !"" favicon.ico
    # !"" images/
    # %"" js/
    %"" templates/
    !"" layouts/
    # %"" default.html.ep
    %"" root/
    %"" index.html.ep

    View Slide

  55. ΑΓ࣮ફతͳΞϓϦ΁

    View Slide

  56. .PKPMJDJPVT-JUFͩͱϑΝΠϧ͕Ͱ͔͘ͳΔΑʔ
    ͦ͜Ͱ-JUF͡Όͳ͍.PKPMJDJPVTΞϓϦʂ
    ϞδϡʔϧΛ͍͍ײ͡ʹ෼͚ͯͭ͘ΕΔ

    View Slide

  57. .PKPMJDJPVTΞϓϦΛͭ͘Δίπ
    w NPKPHFOFSBUFBQQ.Z"QQͰ͸ແ͘
    .Z"QQ8FCΈ͍ͨͳωʔϜεϖʔεͰ
    NPKPHFOFBSBUFBQQ6SBOBJ8FC
    w ͳͥͳΒ6SBOBJ͕8FC૚͚ͩͰ͸ͳ͍͔΋
    w 6SBOBJ.PEFM6SBOBJ-PHJD
    w 6SBOBJ$-*

    View Slide

  58. ͍͍ͩͨ͜Μͳߏ੒
    ./
    !"" Uranai/
    # !"" DB/
    # # %"" Schema.pm
    # !"" DB.pm
    # !"" Model/
    # # %"" OneModel.pm
    # !"" Web/
    # # %"" Controller/
    # # %"" Root.pm
    # %"" Web.pm
    %"" Uranai.pm
    %#ϨΠϠʔ5FOHFUD
    ϏδωεϩδοΫ1FSM.PEVMF
    8FCϨΠϠʔ
    ओʹ$POUSPMMFSͱϧʔςΟϯά
    6SBOBJQNͰ͸ύεղܾͱઃఆϩʔυΛ࣮૷

    View Slide

  59. -JUF͔ΒͷҠߦ
    #!/usr/bin/env perl
    use Mojolicious::Lite;
    get '/' => sub {
    my $self = shift;
    $self->stash->{message} = 'Hello Mojo!';
    $self->render('index');
    };
    app->start;
    __DATA__
    @@ index.html.ep


    <%= $message %>


    MJC6SBOBJ8FCQN
    MJC6SBOBJ8FC$POUSPMMFS
    .PKPMJDJPVT$POUSPMMFSΛܧঝ
    UFNQMBUFT
    .PKP5FNQMBUFʹ४ͣΔ

    View Slide

  60. ͢ΜͳΓҠߦग़དྷΔʂ

    View Slide

  61. ઎͍ΞϓϦΛ࣮૷ͯ͠ΈΔ

    View Slide

  62. ࣮૷ํ਑
    w ઎͍ͷϩδοΫ෦෼Λ.PEFMͱͯ͠੾Γग़͢
    w 6SBOBJ.PEFM6SBOBJ
    w ͦΕΛ$POUSPMMFS͔Βదٓݺͼग़͢
    w 7JFX͸.PKPMJDJPVT-JUFͱಉ͡΋ͷΛ
    ผϑΝΠϧʹ͢Δ

    View Slide

  63. 6SBOBJ.PEFM6SBOBJ
    package Uranai::Model::Uranai;
    use Mouse;
    has 'list' => (
    is => 'ro',
    isa => 'ArrayRef[Str]',
    default => sub {
    [qw/ྑ͍ࣄ͕ى͜ΔͰ͠ΐ͏
    ग़ձ͍͕͋Δ͔΋ʁ
    ෆ޾ʹͳΓ·͢
    /]}
    );
    sub uranau {
    my ($self, $name) = @_;
    my $num = 0;
    $num += ord ($_) for split //, $name;
    my $index = $num % scalar @{$self->list()};
    return $self->list->[$index];
    }
    __PACKAGE__->meta->make_immutable();

    View Slide

  64. .PEFM͸$-*͔Β΋࢖͑Δ
    use Uranai::Model::Uranai;
    use feature 'say';
    my $uranai = Uranai::Model::Uranai->new;
    say $uranai->uranau('yusukebe');
    ͬͯ͜ͱ͸୯ମͰςετग़དྷΔʂ

    View Slide

  65. 6SBOBJ8FC$POUSPMMFS3PPU
    package Uranai::Web::Controller::Root;
    use Mojo::Base 'Mojolicious::Controller';
    use Uranai::Model::Uranai;
    sub index {
    my $self = shift;
    $self->render('index');
    }
    sub result {
    my $self = shift;
    my $name = $self->req->param('name');
    return $self->redirect_to('/') unless $name;
    my $uranai = Uranai::Model::Uranai->new;
    my $message = $uranai->uranau($name);
    $self->stash->{message} = $message;
    $self->render('result');
    }
    1;

    View Slide

  66. ΞϓϦΛͭ͘Δϑϩʔ
    w .PEFMΛॻ͘
    w ςετ͢Δ

    w 3PVUJOH$POUSPMMFSΛॻ͘
    w ςϯϓϨʔτΛॻ͘
    w ςεταʔόΛىಈ͓ͯ͘͠
    w ϒϥ΢βͰ֬ೝ
    w ܁Γฦ͠

    View Slide

  67. $1"/Ϟδϡʔϧͱͷ૊Έ߹Θͤͱ޻෉

    View Slide

  68. .PKPMJDJPVT͚ͩͰ͸଍Γͳ͍
    w $1"/ϞδϡʔϧΛ૊Έ߹Θͤͯͭ͘Δ
    w -JLF-&(0CMPDLT
    .PKPMJDJPVT
    03.BQQFS 'PSN7BMJEBUPS 'JMM*O'PSN FUD

    View Slide

  69. VTF'PSN7BMJEBUPS-JUF
    w ೖྗ஋ͷଥ౰ੑΛνΣοΫ͢Δ
    w ྫɿϝʔϧΞυϨεɺ༣ศ൪߸ɺจࣈ਺
    FormValidator::Lite->load_constraints(qw/Japanese Email/);
    my $validator = FormValidator::Lite->new($self->req);
    my $res -> $validator->check(
    name => [qw/NOT_NULL/],
    mail => [qw/EMAIL/],
    { mails => [qw/mail mail_confirm/] } => ['DUPLICATION']
    );
    if($validator->has_error) {
    $self->stash->{messages} = $validator->get_error_messages();
    return $self->render;
    }
    ...;

    View Slide

  70. VTF5FOH
    w σʔλϕʔεΛૢ࡞͢Δ03.BQQFS
    w ͱͬͯ΋γϯϓϧ
    w $POUSPMMFS͔Β͸ૢ࡞ͤͣ.PEFM͔Β৮Δ
    my $teng = Teng::Schema::Loader->load(
    dbh => $dbh,
    namespace => 'Uranai::DB',
    );
    my $row = $teng->insert(result => {
    text => '͋ͳͨ͸݁ࠗग़དྷ·ͤΜ',
    });

    View Slide

  71. %#Λ༻͍ͨ઎͍ΞϓϦͷԠ༻
    w ݻఆͩͬͨͭͷબ୒ࢶΛ૿΍ͤΔΑ͏ʹ͍ͨ͠

    View Slide

  72. ͪͳΈʹ΍ͬͨ͜ͱ
    CREATE TABLE result (
    id INT UNSIGNED AUTO_INCREMENT,
    text VARCHAR(200) NOT NULL,
    created_at DATETIME NOT NULL,
    PRIMARY KEY (`id`)
    );
    %#Λͭͬͯ͘
    lib/Uranai/DB.pm
    lib/Uranai/DB/Schema.pm
    5FOHͷ%#εΩʔϚͭͬͯ͘
    lib/Uranai/Model/Uranai.pm
    .PEFM͔Βૢ࡞͢ΔΑ͏ʹͯ͠
    lib/Uranai/Controller/Root.pm
    $POUSPMMFS͔Βݺͼग़͢
    templates/root/index.html.ep
    7JFXͷมߋ
    t/01_model.t
    ؆୯ͳςετॻ͍ͯ
    Ͱ͖ͨʂ

    View Slide

  73. ͦͷଞ࣮ફͰ࢖ͬͯΔϞδϡʔϧ
    w )5.-'JMM*O'PSN-JUF
    w %BUB7BMJEBUPS
    w .PVTF
    w 42-.BLFS
    w $BSUPO
    w %FWFM/:51SPG%FWFM,:51SPG
    w 5FTUNZTRME
    w )BSSJFU
    w $JOOBNPO
    w 4FSWFS4UBSUFS
    w 4UBSNBO4UBSMFU
    w FUD
    5IBOLTUPHSFBU.PEVMF"VUIPSTʂ

    View Slide

  74. 5JQT

    View Slide

  75. %&-&5&165Λٖࣅతʹαϙʔτͤ͞Δ
    $self->hook(
    before_dispatch => sub {
    my $c = shift;
    if($c->req->method eq 'POST' && $c->req->param('_method')) {
    my $methods = [qw/GET POST PUT DELETE/];
    if ( grep { $_ eq uc $c->req->param('_method') } @$methods ) {
    $c->req->method( $c->req->param('_method') );
    }
    }
    }
    );
    my $r = $self->routes;
    $r->delete('/entry/:id')->
    to( controller => 'Entry', action => 'delete' );

    View Slide

  76. IFMQFSͰ'JMM*O'PSNΛ͓खܰʹ
    # Uranai::Web
    $self->helper(
    render_fill => sub {
    my ($self, $name) = @_;
    my $html = $self->render(template => $name, partial => 1);
    return $self->render(
    text => HTML::FillInForm::Lite->fill(\$html, $self->req->params),
    format => 'html'
    );
    }
    );
    # Uranai::Web::Controller::*
    sub form {
    my $self = shift;
    ...;
    if ($validator->error) {
    $self->stash->{messages} = $validator->get_error_messages();
    return $self->render_fill('form');
    }
    }

    View Slide

  77. 6SBOBJDPOpH

    # Uranai
    sub config {
    my $mode = $ENV{PLACK_ENV} || 'development';
    my $fname = File::Spec->catfile( Uranai->base_dir() , $mode . '.pl' );
    my $config = undef;
    if( -f $fname ){
    $config = do $fname or die "Cannnot load configuration file: $fname";
    }else{
    die "Cannot find configuration file: $fname";
    }
    return $config;
    }

    View Slide

  78. .PKPMJDJPVTͷηογϣϯʹ͍ͭͯ
    w σϑΥϧτ͸ΫϥΠΞϯτʹΫοΩʔͱͯ͠อ࣋
    w ؾʹೖΒͳ͍৔߹͸
    w 1MBDL.JEEMFXBSF4FTTJPO
    w ࣗ࡞ηογϣϯ؅ཧ

    View Slide

  79. ࠓޙ΁

    View Slide

  80. ঺հͨ͜͠ͱ
    w 8"'ͱ.7$తͳߏ੒ʹ͍ͭͯ
    w ໾ׂΛద੾ʹ෼͚Δ͜ͱͰεοΩϦͱ
    w ରԠ͢Δ.PKPMJDJPVTΛ࢖࣮ͬͨ૷
    w ઎͍ΞϓϦΛྫʹ͋͛ͨ

    View Slide

  81. 8FCΞϓϦΛͭ͘Δʹ͸ʁ
    w ྫ͑͹ࠓճͷ઎͍ΞϓϦ
    w .PKPMJDJPVT-JUFͰ࣮૷ͯ͠ΈΔ
    w ग़དྷͨʂԶͬͯ͹εήʔମݧͦͷ
    w .PKPMJDJPVTΞϓϦͰ֦ுͯ͠ΈΔ
    w ग़དྷͨʂԶͬͯ͹εήʔମݧͦͷ
    w 5FOHΛֶश͠઎͍ͷύλʔϯΛ૿΍͢
    w ग़དྷͨʂԶͬͯ͹εήʔମݧͦͷ

    View Slide

  82. Զͬͯ͹εήʔମݧ
    গͣͭ͠ಈ͍ͯ෼͔Δ

    View Slide

  83. ѻΘͳ͔ͬͨओͳ఺
    w ΑΓποίΜͩ.PKPMJDJPVTͷ࢖͍ํ
    w ςετ5FTU.PSF5FTU.PKP
    w ੜʹ͍ۙ%#42-ૢ࡞
    w ͦͷଞϛυϧ΢ΣΞNFNDBDIFE3FEJT
    w σϓϩΠαʔόߏ੒ΞϓϦαʔό
    w ύϑΥʔϚϯεܭଌɺνϡʔχϯά
    w 1FSMҎ֎ͷ͜ͱ+BWB4DSJQU$44)5.-

    View Slide

  84. ·ͱΊ

    View Slide

  85. .PKPMJDJPVTͰ͸͡ΊΑ͏
    w ബ͍8"'Ώ͑ཧղ͠΍͍͢
    w .PKPMJDJPVT-JUFͷΑ͏ʹগͣͭͭ͘͠ΕΔ
    w ଞͷ8"'ʹ΋Ԡ༻ग़དྷΔ
    ঃʑʹֶ΂ΔϑϨʔϜϫʔΫ

    View Slide

  86. Ωʔϫʔυ͸
    ෼͚Δ͜ͱͰ෼͔Δ
    গͣͭ͠΍Ζ͏

    View Slide

  87. ऴΘΓ
    ࣭͝໰͸ݸผʹʂ

    View Slide