2014-09-26 49 views
1

我在happstack中解析表單,但我不知道更簡潔的方式來收集服務器上的表單變量。 有誰知道是否有任何技巧可以減少這裏所需的代碼量?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" 
+0

'[A,B,C] < - MAPM一下[X ,y,z]'? – user2407038 2014-09-26 07:06:53

回答

1

前言:這顯然是要減少的,你上面貼的代碼量,但是從長遠來看,這可能使事情變得更容易維護,因爲它提供了進行驗證以一致的方式,並允許您處理強類型的對象而不是大量的文本值。

如果你打算做任何數量的表單處理,我會建議使用表單庫。我個人使用過digestive-functors,並且發現與它合作愉快。此外,它還配備了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() 

有關消化仿函數的一些良好的閱讀,你可以看看下面的鏈接:

digestive functors tutorial

ocharles' blog post

+0

太棒了!謝謝! – aqui8 2014-09-27 10:49:21