在声明数据库表/列时,使用Yesod的Persistent模块出错

时间:2014-08-13 19:20:34

标签: mysql database haskell web yesod

我正在尝试使用Yesod的Persistent模块来为我的网站构建我的数据库(在带有Yesod的Haskell中完成)。这是我的模型文件:

User
    idAccount AccountId Int
    userLastName Text Maybe
    userFirstName Text Maybe
    userAge Int Maybe
    userSex Text Maybe
    userEMail Text
    UniqueUserEMail userEMail
Account
    accountName Text
    accountPassword Text
    accountCreatedDate UTCTime default=CURRENT_TIME
    accountLastLogin UTCTime default=CURRENT_TIME
    UniqueAccountName accountName

当我第一次编译时,我收到以下错误:

Model.hs:14:7:                                                                                                                                                                   
    Not in scope: type constructor or class `UTCTime'                                                                                                                            
    In the result of the splice:                                                                                                                                                 
      $(persistFileWith lowerCaseSettings "config/models")                                                                                                                       
    To see what the splice expanded to, use -ddump-splices                                                                                                                       
    In the second argument of `share', namely                                                                                                                                    
      `$(persistFileWith lowerCaseSettings "config/models")'
    In the expression:
      share
        [mkPersist sqlOnlySettings, mkMigrate "migrateAll"]
        ($(persistFileWith lowerCaseSettings "config/models"))

然后我在我的.cabal文件的time部分添加了build-depends模块。这删除了最后一个错误,但我现在有以下错误:

Foundation.hs:135:22:
    Not in scope: data constructor `UniqueUser'
    Perhaps you meant `UniqueDef' (imported from Yesod)

Foundation.hs:140:23:
    `userIdent' is not a (visible) field of constructor `User'

Foundation.hs:141:23:
    `userPassword' is not a (visible) field of constructor `User'

对于第一个错误,根据我的理解(IE,我对yesod book的唯一性约束部分的理解),如果我想使字段唯一,我只需要在最后添加一行表定义以带有空格的字符串“Unique”开头,然后是我想要唯一的字段的名称。我错了吗?

至于最后两个错误,我没有在任何地方声明这些字段,所以我不知道他们为什么在那里。对此有何见解?

2 个答案:

答案 0 :(得分:1)

以下为persistent-1.3.1.1, persistent-mongoDB-1.4.1, persistent-template 1.3.1.4编译。我已经列出了pragma和模块,以防它们成为问题的根源。

{-# LANGUAGE GADTs #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}                                                                                                                                                                              
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DeriveGeneric #-}

import Database.Persist
import Database.Persist.TH
import Database.Persist.MongoDB
import Language.Haskell.TH.Syntax
import Data.Time.Clock.POSIX (getPOSIXTime,posixSecondsToUTCTime)
import Data.Text (Text)
import Data.Time (UTCTime,TimeOfDay)


let mongoSettings = (mkPersistSettings (ConT ''MongoBackend)) {mpsGeneric = False}
    in share [mkPersist mongoSettings] [persistLowerCase|
User
    idAccount AccountId Int
    userLastName Text Maybe
    userFirstName Text Maybe
    userAge Int Maybe
    userSex Text Maybe
    userEMail Text
    UniqueUserEMail userEMail
Account
    accountName Text
    accountPassword Text
    accountCreatedDate UTCTime default=CURRENT_TIME
    accountLastLogin UTCTime default=CURRENT_TIME
    UniqueAccountName accountName
|]

答案 1 :(得分:0)

我找到了错误的来源。由于我使用脚手架网站,已经有一些东西为我实现。其中一个是Yesod Auth模块,它与默认的Persistent模块数据库结构绑定在一起。因此,当我更改models文件中的数据库结构时,它与Foundation.hs文件中的默认Auth模块代码不兼容,即getAuthId函数:

getAuthId creds = runDB $ do
    x <- getBy $ UniqueUser $ credsIdent creds
    case x of
        Just (Entity uid _) -> return $ Just uid
        Nothing -> do
            fmap Just $ insert User
                ( userIdent = credsIdent creds
                , userPassword = Nothing
                )

我不知道如何修改此代码以符合我的目的,所以我会在做完后更新此答案。