Обработка формы с помощью Yesod и использование входных данных для создания чего-то определенного в моделях - PullRequest
1 голос
/ 19 марта 2012

Суть действия в этом файле:

https://github.com/gdoteof/exodus/blob/42c5ee09f09dcb718fa3bdfd79bfe5182c03faaa/Handler/GamingSession.hs

Основная идея, к которой я стремлюсь, - это принять ввод POSTED и использовать этот ввод в сочетании с UTCTime из getCurrentTime для создания новой GamingSession.

Тогда GamingSession будет вставлен в базу данных.

То, что происходит сейчас в / session, - это форма, которая публикует в / session с предварительно заполненными значениями. Но я получаю ошибку

Prelude.read: без разбора

(соответствующие настройки / маршруты: https://github.com/gdoteof/exodus/blob/d07bea21e7699b44739ceadf3c3a18533a9ef462/config/routes )

Ответы [ 5 ]

1 голос
/ 19 марта 2012

Когда у меня есть форма для сохраняемых ключей, я обычно предпочитаю выпадающий список, а не ручной ввод. Попробуйте код ниже. Также попробуйте следовать идиоматическому стилю в книге, это поможет.

gs <- runInputPost $ GamingSession
            start
            Nothing
            <$> ireq (selectField (optionsPersistKey [] [] (toPathPiece . entityKey))) "player"
            <*> ireq (selectField (optionsPersistKey [] [] (toPathPiece . entityKey))) "table"
            <*> iopt intField "seat"

-- | The optionsPersist builtin to the Yesod.Forms package unfortunately only
--   works well with whole persist entities.  We are only interested in the entity
--   id s which is why we add in this function here:
optionsPersistKey
  :: (YesodPersist master
     , PersistEntity a
     , PersistQuery (YesodPersistBackend master) (GHandler sub master)
     , PathPiece (Key (YesodPersistBackend master) a)
     , RenderMessage master msg
     , PersistEntityBackend a ~ YesodPersistBackend master) 
  => [Filter a] 
  -> [SelectOpt a] 
  -> (Entity a -> msg) 
  -> GHandler sub master (OptionList (Key (PersistEntityBackend a) a))
optionsPersistKey filts ords toDisplay = fmap mkOptionList $ do
    mr <- getMessageRender
    pairs <- runDB $ selectList filts ords
    return $ map (\(Entity key value) -> Option
        { optionDisplay = mr (toDisplay $ Entity key value)
        , optionInternalValue = key
        , optionExternalValue = toPathPiece key
        }) pairs
1 голос
/ 19 марта 2012

Вы получаете ошибку чтения, т.к. вы пытаетесь прочитать значения типа "4f6150251c21230c78000000" в PersistInt64.Серверная часть MongoDB не использует PersistInt64 для значений ключей, поэтому код не будет создавать правильный ключ для вашей установки.Я бы попробовал PersistText.

0 голосов
/ 19 марта 2012

изменение

textToKey = Key . PersistText . read . unpack

до

textToKey a = fromJust . fromPathPiece $ a

исправил это для меня

0 голосов
/ 19 марта 2012

Хорошо, попробуйте это:

import Data.Text (unpack)

...

(player, table, seat) <- runInputPost $ (,,)
            <$> (ireq textField "player")
            <*> (ireq textField "table")
            <*> iopt intField "seat"
playerId <- maybe (invalidArgs ["couldn't parse: ", player]) return $ fromPathPiece player
tableId <- maybe (invalidArgs ["couldn't parse: ", table]) return $ formPathPiece table
let gs = GamingSession start Nothing playerId tableId seat 
... 
0 голосов
/ 19 марта 2012

Полученная ошибка означает, что ввод не похож на обычное целое число. Как на самом деле выглядят предварительно заполненные значения? Строки из ireq textField "player" и ireq textField "table" должны , просто содержат число, возможно, дополненное пробелом.

Кроме того, чтобы упростить обработку неудачных парсингов, вам следует взглянуть на safe package . Он содержит версию read (и аналогичные функции), которая возвращает Maybe, поэтому вы получите Nothing вместо исключения, если он не может проанализировать ввод.

...