简体   繁体   English

从数据库中检索消化函子的选择列表(捕捉/抢劫)

[英]Retrieving a list of choices for Digestive Functors from the database (Snap/Heist)

I have an address form that handles both adding and editing (Nothing if adding, Just Address if editing). 我有一个地址表,可以处理添加和编辑(添加时不显示任何内容,编辑时仅显示地址)。 Up until now, I've had the state and country choices hard coded with a handful of items. 到现在为止,我已经对州和国家/地区的选择进行了硬编码,并带有少量项目。

addressForm :: Monad m => Maybe Address -> [Address] -> Form Text m Address
addressForm a addrs = 
    Address
        <$> "id" .: choiceWith (addrToChoice addrs) (fmap id a)
        <*> "name" .: string (fmap name a)
        <*> "street" .: string (fmap street a)
        <*> "city" .: string (fmap city a)
        <*> "state" .: choiceWith stateChoices (fmap state a)
        <*> "country" .: choiceWith countryChoicesRequired (fmap country a)
        <*> "zipcode" .: string (fmap zipcode a)


stateChoices :: [(Text, (Maybe String, Text))] -- (htmlValue, (realValue, labelValue))
stateChoices = [("ON", (Just "ON", "Ontario")), ("NE", (Just "NE", "Nebraska"))]

countryChoicesRequired :: [(Text, (String, Text))]
countryChoicesRequired = [("CA", ("CA", "Canada")), ("US", ("US", "United States of America"))]

Now I would like to retrieve the list of states and countries from the database. 现在,我想从数据库中检索州和国家/地区的列表。 I could just pass the list of states/countries to the form like I'm already doing with a list of addresses, but this form is also a subform of 3 or 4 other forms (new advertiser form, new client form, etc.) and I don't need the list of states/countries outside of the form like I do with the list of addresses. 我可以将州/国家/地区列表传递给表单,就像我已经在处理地址列表一样,但是此表单还是3或4种其他表单(新广告客户表单,新客户表单等)的子表单。而且我不需要像表格中的地址列表那样的表格以外的州/国家列表。

Here's the new form where I've just added fetching the country information: 这是我刚刚添加的用于获取国家/地区信息的新表格:

addressForm' :: (HasPostgres p, Monad m) => Maybe Address -> [Address] -> p (Form Text m Address)
addressForm' a addrs = do
    countries <- countryChoices'
    return $ Address
        <$> "id" .: choiceWith (addrToChoice addrs) (fmap id a)
        <*> "name" .: string (fmap name a)
        <*> "street" .: string (fmap street a)
        <*> "city" .: string (fmap city a)
        <*> "state" .: choiceWith stateChoices (fmap state a)
        <*> "country" .: choiceWith countries (fmap country a)
        <*> "zipcode" .: string (fmap zipcode a)

data Region = Region
    { code :: String
    , fullName :: String
    }

countryChoices' :: HasPostgres m => m [(Text, (String, Text))]
countryChoices' = do
    countries <- getCountries
    return $ abbrToChoice countries

abbrToChoice :: [Region] -> [(Text, (String, Text))]
abbrToChoice regions =
    map (\ a -> ((pack $ code a), (code a, (pack $ fullName a)))) regions

Here's the handler that's calling it: 这是调用它的处理程序:

editAddressH :: ([(T.Text, Splice AppHandler)] -> AppHandler ()) -> Addr.Address -> Maybe Int64 -> AppHandler ()
editAddressH renderer a userId = do
    addresses <- Addr.list userId
    (view, result) <- runForm "form" $ Addr.addressForm' (Just a) addresses -- line 233
    case result of
        Just x -> do
            r <- Addr.edit x -- line 236
            case r of
                _ -> renderer [("success", showContents), ("dfForm", hideContents)]
        Nothing -> renderer $ ("success", hideContents) : ("addressList", addressScriptSplice addresses) : phoneSplices ++ digestiveSplices view

The error I get is this: 我得到的错误是这样的:

src/Site.hs:233:44:
    No instance for (HasPostgres
                       (digestive-functors-0.5.0.1:Text.Digestive.Form.Internal.FormTree
                          (Handler App App) v0 (Handler App App)))
      arising from a use of `Addr.addressForm''
    Possible fix:
      add an instance declaration for
      (HasPostgres
         (digestive-functors-0.5.0.1:Text.Digestive.Form.Internal.FormTree
            (Handler App App) v0 (Handler App App)))
    In the second argument of `($)', namely
      `Addr.addressForm' (Just a) addresses'
    In a stmt of a 'do' expression:
        (view, result) <- runForm "form"
                        $ Addr.addressForm' (Just a) addresses
    In the expression:
      do { addresses <- Addr.list userId;
           (view, result) <- runForm "form"
                           $ Addr.addressForm' (Just a) addresses;
           case result of {
             Just x -> do { ... }
             Nothing
               -> renderer
                $   ("success", hideContents)
                  :   ("addressList", addressScriptSplice addresses)
                    :   phoneSplices ++ digestiveSplices view } }
src/Site.hs:236:40:
    Couldn't match expected type `Addr.Address'
                with actual type `digestive-functors-0.5.0.1:Text.Digestive.Form.Internal.FormTree
                                    m0 Text m0 Addr.Address'
    Expected type: Addr.Address
      Actual type: Form Text m0 Addr.Address
    In the first argument of `Addr.edit', namely `x'
    In a stmt of a 'do' expression: r <- Addr.edit x

Looks like you need the monadic function. 看起来您需要单子函数。 It might look something like this: 它可能看起来像这样:

addressForm :: Monad m => Maybe Address -> [Address] -> Form Text m Address
addressForm a addrs = monadic $ do
    stateChoices <- getStatesFromDB
    countryChoices <- getCountriesFromDB
    return $
      Address
          <$> "id" .: choiceWith (addrToChoice addrs) (fmap id a)
          <*> "name" .: string (fmap name a)
          <*> "street" .: string (fmap street a)
          <*> "city" .: string (fmap city a)
          <*> "state" .: choiceWith stateChoices (fmap state a)
          <*> "country" .: choiceWith countryChoices (fmap country a)
          <*> "zipcode" .: string (fmap zipcode a)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM