[英]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 ()
為了更好地了解消化函子,您可以查看以下鏈接:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.