snap-web-routes 0.3.0.0 → 0.3.0.1
raw patch · 4 files changed
+117/−102 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- README.md +106/−4
- changelog +9/−0
- snap-web-routes.cabal +2/−2
- src/Snap/Web/Routes.hs +0/−96
README.md view
@@ -1,7 +1,109 @@-# snap-web-routes: Type safe URLs for Snap+# snap-web-routes -`snap-web-routes` provides type safe URLs for Snap using [`web routes`](http://hackage.haskell.org/package/web-routes).+## Type safe URLs for Snap -# How to use+[`Snap web routes`](http://hackage.haskell.org/package/snap-web-routes) provides type safe URLs for Snap using [`web routes`](http://hackage.haskell.org/package/web-routes). -See `Snap.Web.Routes` for instructions.+## How to use++The tutorial assumes you have a standard Snap app layout with an Application.hs and Site.hs. If your setup differs you'll need to adapt the instructions accordingly.++### `Application.hs`++To get going, you'll need to add a few things to `Application.hs`. This includes creating the URL data type and adding the routing function to our `App` data type.++ -- Enable a few extensions+ {-# LANGUAGE FlexibleInstances #-} -- Needed by+ {-# LANGUAGE TypeFamilies #-} -- web-routes+ {-# LANGUAGE DeriveGeneric #-} -- Needed to derive Generic+ -- for our URL data type++ -- Paths and params use Text.+ import Data.Text (Text)++ -- Snap.Web.Routes.Types exports everything you need to+ -- define your PathInfo and MonadRoute instances.+ import Snap.Web.Routes.Types++ -- Your URL data type. Deriving a `Generic` instance gives+ -- you a `PathInfo` instance for free.+ data AppUrl+ = Count Int+ | Echo Text+ | Paths [Text]+ deriving (Generic)++ -- Extend your App type to include a routing function.+ data App = App+ { _routeFn :: AppUrl -> [(Text, Maybe Text)] -> Text+ }++ -- Thanks to the wonders of Generic, an empty instance+ -- definition is all we need. Alternately, you can implement+ -- toPathSegments and fromPathSegments yourself or use+ -- web-routes-th.+ instance PathInfo AppUrl++ -- Set URL (Handler App App) to your URL data type defined above+ -- and askRouteFn must point to the routing function you added to+ -- your App.+ instance MonadRoute (Handler App App) where+ type URL (Handler App App) = AppUrl+ askRouteFn = gets _routeFn++### `Site.hs`++Moving on to `Site.hs`, we'll setup handlers for each URL, as well initialise our app with a routing function.++ -- Snap.Web.Routes provides routing functions+ import Snap.Web.Routes++ -- Add your new routes using routeWith+ routes :: [(ByteString, Handler App App ())]+ routes = [ ("", routeWith routeAppUrl)+ , ("", serveDirectory "static")+ ]++ -- Define handlers for each value constructor in your URL data type.+ routeAppUrl :: AppUrl -> Handler App App ()+ routeAppUrl appUrl =+ case appUrl of+ (Count n) -> writeText $ ("Count = " `T.append` (T.pack $ show n))+ (Echo text) -> echo text+ (Paths ps) -> writeText $ T.intercalate " " ps++ -- You'll note that these are normal Snap handlers, except they can take+ -- values from the value constructor as arguments. This is a lot nicer than+ -- having to use getParam.+ echo :: T.Text -> Handler App App ()+ echo msg = heistLocal (bindString "message" msg) $ render "echo"++ -- Add the routing function to your app.+ app :: SnapletInit App App+ app = makeSnaplet "app" "An example snap-web-routes app." Nothing $ do+ addRoutes routes+ return $ App renderRoute++If you prefixed the routes in routeWith (e.g. `("/prefix", routeWith routeAppUrl)`) then use `renderRouteWithPrefix` instead:++ return . App $ renderRouteWithPrefix "/prefix"++If you are having trouble figuring out why a particular request isn't routing as expected, try replacing `routeWith` with `routeWithDebug`. It'll display the available routes, as well as any failed route parses. Just remember that it's **not suitable for production** use.++### Rendering URLs++Helper functions are provided for rendering URLs:++ echo :: T.Text -> Handler App App ()+ echo msg = do+ url <- showUrl $ Echo "this is a test"+ if msg == "test" then redirect (encodeUtf8 url) else renderEcho+ where+ renderEcho = heistLocal (I.bindSplices echoSplices) $ render "echo"+ echoSplices = do+ "message" ## I.textSplice msg+ "countUrl" ## urlSplice (Count 10)++In the example above you'll find we use `urlSplice` to turn a URL into a splice, and `showUrl` to render a URL as Text.++
changelog view
@@ -1,3 +1,12 @@+2014-05-06 0.3.0.1++* Move tutorial to readme as it didn't show up on Hackage++2014-05-06 0.3.0.0++* Rename heistUrl to urlSplice+* Add convenience functions to render routes as Text+ 2014-05-06 0.2.0.0 * Document functions properly
snap-web-routes.cabal view
@@ -1,10 +1,10 @@ name: snap-web-routes-version: 0.3.0.0+version: 0.3.0.1 synopsis: Type safe URLs for Snap description: Type safe URL generation and routing for Snap using web-routes. .- To get started, run through the tutorial in Snap.Web.Routes.+ To get started, there is a __<https://github.com/lukerandall/snap-web-routes/blob/master/README.md tutorial on GitHub>__. . This builds on <https://github.com/stepcut/snap-web-routes-demo work> done by Jeremy Shaw. Thanks Jeremy!
src/Snap/Web/Routes.hs view
@@ -1,102 +1,6 @@ -- | -- This module provides a ready to use implementation of `web-routes` for Snap. ----- The tutorial assumes you have a standard Snap app with an Application.hs and--- Site.hs.------ To get going, you'll need to add a few things to Application.hs------ @--- -- Enable a few extensions------ \-\- Needed to derive a generic instance for our URL data type--- \{\-\# LANGUAGE DeriveGeneric \#\-\}------ \-\- Needed by web-routes--- \{\-\# LANGUAGE FlexibleInstances \#\-\}--- \{\-\# LANGUAGE TypeFamilies \#\-\}------ \-\- Paths and params are of type Text.--- import Data.Text (Text)------ \-\- Snap.Web.Routes.Types exports everything you need to--- \-\- define your PathInfo and MonadRoute instances.--- import Snap.Web.Routes.Types------ \-\- Your URL data type. Deriving a `Generic` instance gives--- \-\- you a `PathInfo` instance for free.--- data AppUrl--- = Count Int--- | Echo Text--- | Paths [Text]--- deriving (Generic)------ \-\- Extend your App type to include a routing function.--- data App = App--- { _routeFn :: AppUrl -> [(Text, Maybe Text)] -> Text--- }------ \-\- Thanks to the wonders of Generic, an empty instance--- \-\- definition is all we need. Alternately, you can implement--- \-\- toPathSegments and fromPathSegments yourself or use--- \-\- web-routes-th.--- instance PathInfo AppUrl------ \-\- Set URL (Handler App App) to your URL data type defined above--- \-\- and askRouteFn must point to the routing function you added to--- \-\- your App.--- instance MonadRoute (Handler App App) where--- type URL (Handler App App) = AppUrl--- askRouteFn = gets _routeFn--- @------ Moving on to Site.hs.------ @--- \-\- Snap.Web.Routes provides routing functions--- import Snap.Web.Routes------ \-\- Add your new routes using routeWith--- routes :: [(ByteString, Handler App App ())]--- routes = [ ("", routeWith routeAppUrl)--- , ("", serveDirectory "static")--- ]------ \-\- Define handlers for each value constructor in your URL data type.--- routeAppUrl :: AppUrl -> Handler App App ()--- routeAppUrl appUrl =--- case appUrl of--- (Count n) -> writeText $ ("Count = " `T.append` (T.pack $ show n))--- (Echo text) -> echo text--- (Paths ps) -> writeText $ T.intercalate " " ps------ \-\- You'll note that these are normal Snap handlers, except they can take--- \-\- values from the value constructor as arguments. This is a lot nicer than--- \-\- having to use getParam.--- echo :: T.Text -> Handler App App ()--- echo msg = heistLocal (bindString "message" msg) $ render "echo"------ \-\- Add the routing function to your app.--- app :: SnapletInit App App--- app = makeSnaplet "app" "An example snap-web-routes app." Nothing $ do--- addRoutes routes--- return $ App renderRoute--- @------ If you prefixed the routes in routeWith------ > ("/prefix", routeWith routeAppUrl)------ then use `renderRouteWithPrefix` instead:------ > return . App $ renderRouteWithPrefix "/prefix"------ If you are having trouble figuring out why a particular request isn't routing--- as expected, try replacing 'routeWith' with 'routeWithDebug'. It'll display--- the available routes, as well as any failed route parses. Just remember that--- it's not suitable for production use.-- module Snap.Web.Routes ( routeWith , routeWithDebug