使用持久性getJust与entityIdToJSON的问题

时间:2014-07-31 11:54:36

标签: json haskell persistent scotty

我是Haskell的新手,我正在尝试使用Persistent编写一个Scotty Web API作为ORM。我遇到以下代码问题:

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Account json
  name        String
  description T.Text
  deriving Show
...
|]

resource :: (PersistEntity a, PersistEntityBackend a ~ SqlBackend, ToJSON a, ToJSON (Entity a), FromJSON a) => String -> (Key a -> Key a) -> [SelectOpt a] -> Pool Connection -> S.ScottyM ()
resource url keyConv selectOpts pool = do

  S.get (S.capture $ pluralize url) $ do
    objects <- runDb pool $ selectList [] selectOpts
    S.json $ map entityIdToJSON objects

  S.get (S.capture $ url ++ "/:id") $ do
    idParam <- S.param "id"
    found <- runDb pool . getJust . keyConv . key $ idParam
    S.json $ found

  ...

main :: IO ()
main = withSqlitePool "bla.db" 2 $ \pool -> do
  S.scotty 3000 $ do
    resource "/account" accountKey [Asc AccountId] pool
    ...

resource函数为我想要公开的持久模型对象定义Scotty Web路由。

resource定义的第一条路线检索整个集合。例如。 HTTP GET/accounts会返回所有帐户。

resource定义的第二个路由按ID检索特定实体。例如。 HTTP GET/account/1会返回ID为1的帐户。

这些函数按原样工作,但我不喜欢默认的json序列化如何不包含id,这就是我在get all路由中使用entityIdToJSON的原因。

但是,当尝试在get by id路由中包含entityIdToJSON时,在S.json $ found的行上,我收到以下类型错误:

Main.hs:61:31-35: Could not deduce (a ~ Entity e0) …                                                                                                            
    from the context (PersistEntity a,                                                                                                                          
                      PersistEntityBackend a ~ SqlBackend,                                                                                                      
                      ToJSON a,                                                                                                                                 
                      ToJSON (Entity a),                                                                                                                        
                      FromJSON a)                                                                                                                               
      bound by the type signature for                                                                                                                           
                 resource :: (PersistEntity a, PersistEntityBackend a ~ SqlBackend,                                                                             
                              ToJSON a, ToJSON (Entity a), FromJSON a) =>                                                                                       
                             String                                                                                                                             
                             -> (Key a -> Key a)                                                                                                                
                             -> [SelectOpt a]                                                                                                                   
                             -> Pool Connection                                                                                                                 
                             -> S.ScottyM ()                                                                                                                    
      at /home/poida/src/moneymoney-api-scotty/Main.hs:48:13-189                                                                                                
      `a' is a rigid type variable bound by                                                                                                                     
          the type signature for                                                                                                                                
            resource :: (PersistEntity a, PersistEntityBackend a ~ SqlBackend,                                                                                  
                         ToJSON a, ToJSON (Entity a), FromJSON a) =>                                                                                            
                        String                                                                                                                                  
                        -> (Key a -> Key a)                                                                                                                     
                        -> [SelectOpt a]                                                                                                                        
                        -> Pool Connection                                                                                                                      
                        -> S.ScottyM ()                                                                                                                         
          at /home/poida/src/moneymoney-api-scotty/Main.hs:48:13                                                                                                
    In the second argument of `($)', namely `found'                                                                                                             
    In the second argument of `($)', namely `entityIdToJSON $ found'                                                                                            
    In a stmt of a 'do' block: S.json $ entityIdToJSON $ found                                                                                                  
Compilation failed.

我尝试将类型约束Entity a添加到资源中,这会让事情变得更糟。我也试过在hackage的文档中挖掘,但我不太了解我正在阅读的所有内容。 The docs似乎表明密钥是实体及其密钥。

tl; dr - 我的问题是尝试使用Persistent的getJust函数的结果,一个Key,使用Persistent的entityIdToJSON函数,该函数需要一个实体。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我认为您需要将密钥与found结合使用才能生成Entity

将您传递的密钥存储到getJust(将该分隔线分开以存储keyConv . key $ idParam中的let),然后从存储的密钥和{Entity中创建found {1}}。

像(未经测试)的东西:

  S.get (S.capture $ url ++ "/:id") $ do
    idParam <- S.param "id"
    let k = keyConv . key $ idParam
    found <- runDb pool . getJust $ k
    S.json $ Entity k found