2016年7月17日日曜日

[haskell][yesod] stack対応版Yesod tutorial

HaskellのwebサービスフレームワークにYesodというフレームワークがあります。Yesodに触れたことのない開発者向けに書かれたチュートリアルの一つにYesod tutorialがあり、手順に沿っていくだけで簡単なwebサービスを動作させることができ、Yesodで何ができるかを簡単に理解できるようになっています。
ただ残念なことに、このYesod tutorialの記載は内容が古く、stackを利用した現行の手順とマッチしなくなっています。stackに対応している最新環境(Yesod 1.4.x)における順があると役に立つと思い、書き起こしてみました。

  1. Before the real start(はじめに)
    1. Install(インストール手順)
    2. stackをインストールする。以下のサイトが参考になります。
    3. Initialize(初期化)
    4. オリジナルのチュートリアルではyesod initの実行する手順が記載されていますが、最新版のYesodでは以下のようにstack newを利用するよう指示されます。
      // original
      % yesod init
      yesod: The init command has been removed. Please use 'stack new' instead
      
      stack対応版では、以下のようにテンプレートを指定してプロジェクトを生成します。これでオリジナル版でプロジェクト名にyosogを、利用DBにsqliteを指定したのと同じ状態になっています。
      // stack support
      % stack new my-project yesod-sqlite
      
      次にyosogプロジェクトをビルドします。オリジナルの手順は以下のようになっています。
      // original
      % cd yosog
      % cabal sandbox init
      % cabal install --enable-tests . yesod-platform yesod-bin --max-backjumps=-1 --reorder-goals
      % yesod devel
      
      これに対応する、stack版での手順は以下になります。
      // stack support
      % cd my-project
      % stack build yesod-bin cabal-install --install-ghc
      % stack build
      % stack exec -- yesod devel
      
      あとはブラウザを起動して http://localhost:3000/ にアクセスすればscaffolding siteの画面が表示されます。ただ、環境によっては"getAddrInfo: does not exist"というエラーが表示され、scaffolding siteに繋がらない現象があるので、そのときにはこちらの情報を参考に対処してください。
    5. Configure git
    6. 「この作業は必須ではありませんが、gitを使うことはよい習慣です」だそうです
      % git init .
      % git add .
      % git commit -a -m "Initial yesod commit"
      
    7. A few words before we start
    8. my-project以下のディレクトリ構成の概要:
      config/routesURLとコードのマッピング設定ファイル
      Handler/URLにマッピングされたコード(ハンドラ)を格納
      templates/HTMLファイル、js, cssテンプレートファイルを格納
      config/modelsデータモデル(DBスキーマ)設定ファイル
  2. Echo
  3. さてEchoサーバーの実装です。最初の手順としてオリジナルサイトには以下のコマンド実行が記載されています。
    // original
    $ yesod add-handler
    
    stack対応版ではyesodコマンドを直に実行することはできません。かならず"stack exec"を介する必要があります。具体的には以下のコマンドを実行すればOKです。
    // stack support
    % stack exec -- yesod add-handler
    Name of route (without trailing R): Echo
    Enter route pattern (ex: /entry/#EntryId): /echo/#String
    Enter space-separated list of methods (ex: GET POST): GET
    
    上記手順でEchoハンドラを登録することができます。そして本来ならばこの状態で何も編集を加えなくてもビルドができるはずなのですが、以下のエラーが発生してしまいました・・・。
    % stack exec -- yesod devel
    Yesod devel server. Type 'quit' to quit
    Application can be accessed at:
    
    http://localhost:3000
    https://localhost:3443
    If you wish to test https capabilities, you should set the following variable:
      export APPROOT=https://localhost:3443
    
    Warning: The package list for 'hackage.haskell.org' is 146.2 days old.
    Run 'cabal update' to get the latest list of available packages.
    Resolving dependencies...
    Configuring my-project-0.0.0...
    ghc: unable to load package `my-project-0.0.0'
    ghc: C:\work_haskell\yesodweb\scaffolding\my-project\dist\build\HSmy-project-0.0.0-5AgQdK8FuSe8tlY0YoDpHN.o: unknown symbol `myprozu5AgQdK8FuSe8tlY0YoDpHN_HandlerziEcho_getEchoR_closure'
    
    確認したところ、add-hanlderコマンドによってmy-project.cabalに追加された、Handler.Echoの追加場所が正しくなく、リンクエラーになっている模様。
    --- a/yesodweb/scaffolding/my-project/my-project.cabal
    +++ b/yesodweb/scaffolding/my-project/my-project.cabal
    @@ -101,6 +101,7 @@ test-suite test
         other-modules:     Handler.CommentSpec
                            Handler.CommonSpec
                            Handler.HomeSpec
    +                       Handler.Echo
                            TestImport
         hs-source-dirs:    test
         ghc-options:       -Wall
    
    自動追加された上記の状態ではダメで、以下の場所に移動する必要がある。add-handlerの不具合により、.cabalファイル内の"library"欄に追加する項目が"test suite"欄に追加されてしまうのが原因です。
    --- a/yesodweb/scaffolding/my-project/my-project.cabal
    +++ b/yesodweb/scaffolding/my-project/my-project.cabal
    @@ -23,6 +23,7 @@ library
                          Handler.Common
                          Handler.Home
                          Handler.Comment
    +                     Handler.Echo
     
         if flag(dev) || flag(library-only)
             cpp-options:   -DDEVELOPMENT
    
    これでコンパイルが無事に通り、scafolding siteを起動できる状態になります。tutorialに沿ってブラウザから以下のURLにアクセスしてみます。
    現時点ではまだハンドラの実装が空のままなので、以下のエラーが返されるのが期待値になります。
    いよいよ、Echoハンドラの実装です。 エディタでHandler/Echo.hsを開いてみてください。以下のようになっているはずです(前述のNot yet implementedエラーはこのコードによるものです)。
    module Handler.Echo2 where
    
    import Import
    
    getEcho2R :: String -> Handler Html
    getEcho2R string = error "Not yet implemented: getEcho2R"
    
    Handler/Echo.hsを以下の実装に変えることでEchoが動作する状態になります。
    module Handler.Echo where
    
    import Import
    
    getEchoR :: String -> Handler Html
    getEchoR theText = defaultLayout [whamlet|<h1>#{theText}|]
    
    試しにブラウザから以下のURLにアクセスしてみましょう!
    以下の通り"foo"がエコーバックされれば成功です。

オリジナルのチュートリアルではEchoサーバーの実装後、以下の手順が案内されています。yesodコマンド実行時にstack execを適用することで問題なく進められると思います。
    2. Echo
    2.1. Bulletproof?
    2.2. Cleaning up
    2.2.1. Data.Text
    2.2.2. Use templates
    3. Mirror
    4. A Blog
一通りの手順を実装したコードをgithubの以下のサイトにコミットしています。必要に応じてこちらも参照してみてください。

環境:

  • The Glorious Glasgow Haskell Compilation System, version 7.10.3
  • yesod-bin version: 1.4.17.1

参考:


0 件のコメント:

コメントを投稿