packages feed

happs-tutorial 0.8.1 → 0.9.0

raw patch · 6 files changed

+168/−16 lines, 6 filesdep ~DebugTraceHelpersdep ~HStringTemplatedep ~HStringTemplateHelpers

Dependency ranges changed: DebugTraceHelpers, HStringTemplate, HStringTemplateHelpers, HTTP, bytestring, containers, directory, filepath, happstack, happstack-data, happstack-helpers, happstack-ixset, happstack-server, happstack-state, hscolour, mtl, old-time, parsec, pretty, pureMD5, safe

Files

happs-tutorial.cabal view
@@ -1,5 +1,5 @@ Name:                happs-tutorial-Version:             0.8.1+Version:             0.9.0 Synopsis:            A Happstack Tutorial that is its own web 2.0-type demo.  Description:         A nice way to learn how to build web sites with Happstack @@ -46,10 +46,28 @@         MiscMap         ControllerStressTests         View-    ghc-options: -Wall-    Build-Depends:   base, HStringTemplate, HStringTemplateHelpers, mtl, bytestring,-                     happstack, containers, pretty, pureMD5, directory, filepath, hscolour, -                     HTTP, safe, old-time, parsec, happstack-helpers, DebugTraceHelpers,-                     happstack-server, happstack-data, happstack-ixset, happstack-state+    ghc-options: -Wall -O2+    Build-Depends:   base+                     , HStringTemplate >= 0.4.0 && < 0.5.0+                     , HStringTemplateHelpers > 0.0.0 && < 1.0.0+                     , mtl >= 1.1.0.0 && < 2.0.0.0 +                     , bytestring >= 0.9.0.0 && < 0.10.0.0+                     , happstack >= 0.3 && < 0.4+                     , containers >= 0.2.0.0 && < 0.3.0.0+                     , pretty >= 1.0.1.0 && < 2 +                     , pureMD5 >= 1.0.0.0 && < 1.1.0.0+                     , directory >= 1.0.0.0 && < 1.1.0.0+                     , filepath >= 1.1.0.0 && < 1.2.0.0+                     , hscolour >= 1.0 && < 2.0+                     , HTTP >= 4000.0.7 && < 4000.0.8+                     , safe >= 0.2 && < 0.3+                     , old-time >= 1.0.0.0 && < 1.1.0.0+                     , parsec >= 2.1.0.0 && < 2.2.0.0+                     , happstack-helpers >= 0.30 && < 0.40+                     , DebugTraceHelpers >= 0.12 && < 0.20+                     , happstack-server >= 0.3 && < 0.4+                     , happstack-data >= 0.3 && < 0.4+                     , happstack-ixset >= 0.3 && < 0.4+                     , happstack-state >= 0.3 && < 0.4     if flag(base4)       Build-Depends: base >=4 && <5, syb
+ src/GetExample.hs view
@@ -0,0 +1,83 @@+{-# OPTIONS_GHC -F -pgmFtrhsx #-}++import Happstack.Server+import HSP+import Happstack.Server.HSP.HTML+import Data.Monoid++{- We define a very simple data type here to use as our+   instance for FromData -}+data Foo = Foo {bar :: Int,+                baz :: Int}+         deriving Show++{- Defining an instance of FromData is fundamentally simple.  Primarily, you should use the helper function look+to grab the string associated with the named parameter you provide.  From there, we use read to parse the string into an+int and return the final Foo.  This isn't the safest construction, because the read could fail, but you can easily provide+yourself with more safety by using the MonadPlus instance of RqData and just calling mzero when an error occurs.-}+instance FromData Foo where+    fromData = do+      x <- read `fmap` look "bar"+      y <- read `fmap` look "baz"+      return $ Foo x y++main :: IO ()+main = simpleHTTP nullConf{port=8080} $ (dir "getHandler" handler) `mappend` (dir "postHandler" handler) `mappend` home++{- Please note that we actually use the same handler for both GET & POST requests.  +   This is an advantage of using FromData.+-}+handler :: ServerPartT IO Response+handler = do+  mfoo <- getData+  case mfoo of+    Nothing -> webHSP $ didn'twork+    Just foo -> webHSP $ displayFoo foo++displayFoo :: Foo -> HSP XML+displayFoo f = <html>+                <head>+                 <title>This is a Foo</title>+                </head>+                <body>+                 <p>Here, look at a Foo:  <%show f%></p>+                 <p><a href="/">home</a></p>+                </body>+               </html>++didn'twork = <html>+              <head>+               <title>Something is wrong!</title>+              </head>+              <body>+               <p>Something has gone horribly wrong+                 <a href="/">go home</a></p>+              </body>+             </html>++home :: ServerPartT IO Response+home = webHSP $ <html>+                 <head>+                  <title>Get and Post examples</title>+                 </head>+                 <body>+                  <form action="getHandler" method="GET">+                    <p>+                     <label for="bar">Bar:  </label>+                     <input type="text" name="bar" /><br/>+                     <label for="baz">Baz:  </label>+                     <input type="text" name="baz" /><br/>+                     <input type="submit" value="Send" />+                    </p>+                  </form>+                  <form action="postHandler" method="POST">+                    <p>+                     <label for="bar">Bar:  </label>+                     <input type="text" name="bar" /><br/>+                     <label for="baz">Baz:  </label>+                     <input type="text" name="baz" /><br/>+                     <input type="submit" value="Send" />+                    </p>+                  </form>+                 </body>+                </html>
+ src/HSPExample.hs view
@@ -0,0 +1,31 @@+{-# OPTIONS_GHC -F -pgmFtrhsx #-}+-- You might be wondering what's the point of this options declaration.  +-- It enables a particular preprocessor that allows the literal HTML syntax+-- for HSP.  Without it this example cannot compile.++import Happstack.Server+import Happstack.Server.HSP.HTML+import HSP+import System.Random++main :: IO ()+main = simpleHTTP nullConf{port=8080} home++{- Integrating HSP into Happstack is very simple.  One just lifts the HSP value into a ServerPartT with webHSP from+ Happstack.Server.HSP.HTML -}+home :: ServerPartT IO Response+home = webHSP $ <html>+                 <head>+                  <title>Simple HSP w/ Happstack Example</title>+                 </head>+                 <body>+                  <h1>HSP can be convenient</h1>+                   <ol>+                    <li>You can include your html in your Haskell file exactly as you'd expect.</li>+                    <li>You can include <%"haskell values"%> very easily in your code.</li>+                    <li>Or even IO actions: <%aux%>.</li> +                    <li>Your HTML is parsed and built at compile time, so that is where mistakes are caught</li>+                   </ol>+                  </body>+                 </html>+  where aux = doIO $ show `fmap` randomRIO (0,100 :: Int)
+ templates/formsanddata.st view
@@ -0,0 +1,23 @@+<h3>GET, POST, and FromData</h3>+<p>We've covered how to serve basic HTML with Happstack, in a number of different ways.  What we haven't yet covered+is what to do with form data.  In principle, you could dig into the request and try to pull out the parameters.  That's+not the Happstack way, though.</p>+<p>Instead, you can use the type class FromData and the functions getData and withData.+A simple example can be found in <a href=/src/GetExample.hs>GetExample.hs<a/>.  This example uses HSP to build+the forms, for simple convenience.</p>+<p>ghci>:i FromData+<br/>class FromData a where fromData :: RqData a+<br/>        -- Defined in Happstack.Server.SimpleHTTP+<br/>instance [overlap ok] (FromData a, FromData b) => FromData (a, b)+<br/>  -- Defined in Happstack.Server.SimpleHTTP+<br/>instance [overlap ok] (FromData a, FromData b, FromData c) => FromData (a, b, c)+<br/>  -- Defined in Happstack.Server.SimpleHTTP+<br/>instance [overlap ok] (FromData a,FromData b,FromData c,FromData d) => FromData (a, b, c, d)+<br/>  -- Defined in Happstack.Server.SimpleHTTP+<br/>instance [overlap ok] (FromData a) => FromData (Maybe a)+<br/>  -- Defined in Happstack.Server.SimpleHTTP+</p>+<p>An important note about RqData is that it is a Monad and a MonadPlus, so between this type class machinery and+the helper function look, you should be able to define your own instances of FromData for your own types.+Again, the simple example up above should provide some guidance for this.</p>+<p>Next we cover <a href="/tutorial/file-uploads">uploading files</a></p>
templates/getandpost.st view
@@ -2,18 +2,18 @@  <p>GET data is data attached to an http request via the url string. In the job board app, an example of this is    <a href=/tutorial/viewprofile?user=tphyahoo>tphyahoo's profile</a>, where the user is specified on the url string.-   Another example is <a href=/tutorial/viewjob?user=tphyahoo&job=darcshub>fetching a particular job</a>.+   Another example is <a href=/tutorial/viewjob?user=tphyahoo&job=darcshub>fetching a particular job</a>.</p>  <p>POST data is data attached to a request after submitting a form.    One place this is used is in the <a href=/tutorial/register>registration</a> process.-   Once you have a user created, you can also see POST in action by editing your profile or creating jobs.+   Once you have a user created, you can also see POST in action by editing your profile or creating jobs.</p> -<p>Happstack deals with GET and POST data similarly.+<p>Happstack deals with GET and POST data similarly.</p>  <p>Let's look at how-   <a href=/tutorial/viewprofile?user=tphyahoo>tphyahoo's profile</a> gets displayed.+   <a href=/tutorial/viewprofile?user=tphyahoo>tphyahoo's profile</a> gets displayed.</p> -<p><a href=/src/Controller.hs>Controller.hs</a>: ... , dir "viewprofile" [ methodSP GET \$ userProfile rglobs ] ...+<p><a href=/src/Controller.hs>Controller.hs</a>: ... , dir "viewprofile" [ methodSP GET \$ userProfile rglobs ] ...</p>  <p>using dir and methodSP as above is a common pattern. dir pops the head element of the path array    ["viewprofile"], resulting in an empty array. methodSP checks that the path array is empty and that 
templates/whatsnew.st view
@@ -1,7 +1,4 @@-<h3>What's new in version 0.8.1</h3>+<h3>What's new in version 0.9.0</h3> <ul>-<li>New section on IxSets</li>-<li>Simplified migration examples</li>-<li>General cleanups of the tutorial code</li>-<li>Using random numbers in Updates and Queries in MACID intro</li>+<li>Compatibility with new Happstack 0.3.*</li> </ul>