簡體   English   中英

Happstack處理

[英]Happstack handling

我正在解析happstack中的表單,但我不知道在服務器上收集表單變量的更簡潔的方法。 有人知道是否有任何技巧可以減少此處所需的代碼量?

 formHandler = do
    method POST
    delA1       <- look "address-01-delivery"
    delA2       <- look "address-02-delivery"
    delSuburb   <- look "suburb-delivery"
    delPostcode <- look "postcode-delivery"
    delState    <- look "state-delivery"
    delCountry  <- look "country-delivery"

    bilA1       <- look "address-01-billing"
    bilA2       <- look "address-02-billing"
    bilSuburb   <- look "suburb-billing"
    bilPostcode <- look "postcode-billing"
    bilState    <- look "state-billing"
    bilCountry  <- look "country-billing"

前言:這顯然不會減少您在上面發布的代碼量,但是從長遠來看,它可以使事情更易於維護,因為它提供了一種一致的方式來執行驗證,並允許您處理強類型對象而不是大型對象。文本值的數量。

如果您要進行任何形式的表單處理,我建議您使用表單庫。 我親自使用過消化功能器 ,並且發現與它一起工作很有趣。 同樣,它帶有Happstack后端,這使得Happstack集成非常簡單。

這可能比您打算投資的要多,但是這里是使用摘要函子的表單代碼外觀示例。 我沒有嘗試編譯任何一個,因此它可能會或可能不會起作用,但希望它能提供總體思路。

{-# LANGUAGE OverloadedStrings #-}

module Forms where

import Control.Applicative ((<$>), (<*>))
import Data.Text (Text)
import qualified Data.Text as T
import Happstack.Server
import Text.Digestive


data AddressState 
  = Alabama
  | Alaska
  | Arkansas
  -- ...
  deriving (Enum, Eq, Read)

data Country
  = Canada
  | Mexico
  | UnitedStates
  -- ...
  deriving (Enum, Eq, Read)

data Address = Address
  { street1  :: Text
  , street2  :: Maybe Text
  , suburb   :: Maybe Text
  , postcode :: Int
  , state    :: AddressState
  , country  :: Country
  }

data ShippingForm = ShippingForm
  { deliveryAddress :: Address
  , billingAddress  :: Address
  }

addressForm :: (Monad m) => Form Text m Address
addressForm = Address
  <$> "street1"  .: nonEmptyText (text Nothing)
  <*> "street2"  .: optionalText Nothing
  <*> "suburb"   .: optionalText Nothing
  <*> "postcode" .: stringRead "Please enter a valid postcode" Nothing
  <*> "state"    .: choice mkChoices Nothing
  <*> "country"  .: choice mkChoices Nothing
  where
    nonEmptyText = check "Cannot be empty" (not . T.null)
    mkChoices = [(x, T.pack (show x)) | x <- [minBound .. maxBound]]

shippingForm :: (Monad m) => Form Text m ShippingForm
shippingForm = ShippingForm
  <$> "delivery" .: addressForm
  <*> "billing"  .: addressForm

formHandler :: ServerPart Response
formHandler = do
  method POST
  decodeBody $ defaultBodyPolicy "/tmp" 4096 4096 4096
  res <- runForm "shipping" shippingForm
  case res of
    (view, Nothing) -> do
      -- setup your view
      ok $ toResponse () -- <-- replace this with your view code
    (_, Just formData) -> do
      -- here, formData is a fully valid `ShippingForm`
      let delStreet1 = (street1 . deliveryAddress) formData
      -- do whatever you need to with this data (ie: persist it to a database, etc)
      ok $ toResponse ()

為了更好地了解消化函子,您可以查看以下鏈接:

消化函子教程

ocharles的博客文章

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM