我想了解简单的snaplet构造。 另外,我什么时候需要制作一个snaplet和一个简单的侧库? 如果我确实需要一个如何从库中取出它?
例如,我有一堆数据库函数,我将SQL代码包装在下面。
data Person = Person {personName :: ByteString, personAge :: Int}
connect :: IO Connection
connect = connectSqlite3 "/somepath/db.sqlite3"
savePerson :: Person -> IO ()
savePerson p = do
c <- connect
run c "INSERT INTO persons (name, age) \
\VALUES (?, ?)"
[toSql (personName p), toSql (personAge p)]
commit c
disconnect c
每个函数都会启动一个新连接并在提交后关闭连接。 我想制作一个snaplet是避免每个功能连接的方法吗? 在我的处理程序中,我会像这样使用它:
insertPerson :: Handler App App ()
insertPerson = do
par <- getPostParams
let p = top par
liftIO $ savePerson p
where
top m =
Person {personName = head (m ! (B.pack "name"))
,personAge = read (B.unpack (head (m ! (B.pack "age")))) :: Int
}
它到目前为止有效。我的问题是: 我什么时候才能将库变成snaplet?我是否需要将简单的DB库转换为snaplet,以初始化连接而不是在每个函数中建立连接?
现在,如果我制作snaplet ...... 在Snap网站上有一个顶级sanaplet的小例子,但是没有关于如何制作你自己的简单插件snaplet的痕迹。
所以我在我的DB库中添加了snaplet初始化函数
dbInit :: SnapletInit b Connection
dbInit = makeSnaplet "DB" "My DB Snaplet" Nothing $ do
dbc <- liftIO $ connectSqlite3 "/somepath/db.sqlite3"
onUnload $ disconnect dbc
return $ dbc
这是正确的做法吗?这就是我需要把它变成一个可插入的snaplet吗?
然后我将这个DB snaplet堆叠到主应用程序
data App = App
{ _heist :: Snaplet (Heist App),
_dbcon :: Snaplet (Connection)
}
makeLens ''App
app :: SnapletInit App App
app = makeSnaplet "app" "My app" Nothing $ do
h <- nestSnaplet "heist" heist $ heistInit "templates"
d <- nestSnaplet "" dbcon dbInit
addRoutes routes
return $ App h d
现在,我获得的是我的请求处理程序可用的连接,对吧? 所以我的处理程序变为:
insertPerson :: Handler App App ()
insertPerson = do
par <- getPostParams
let person = top par
connection <- gets _dbcon
liftIO $ savePerson connection person
where
top m =
Person {personName = head (m ! (B.pack "name"))
,personAge = read (B.unpack (head (m ! (B.pack "age")))) :: Int
}
这似乎不起作用。我究竟做错了什么?这是从snaplet句柄(dbcon)中提取连接的正确方法吗?这通常是构建简单snaplet的正确方向吗?在我的情况下,我真的需要一个snaplet吗?
感谢。
答案 0 :(得分:4)
Handler
是MonadState
:MonadState v (Handler b v)
的一个实例。
Handler
也是MonadSnaplet
的一个实例,因此提供了with
方法:
with :: Lens v (Snaplet v') -> m b v' a -> m b v a
dbcon
是Lens App (Snaplet Connection)
。
所以要到Connection
,我们可以使用:
conn <- with dbcon get
如果您提供的功能可以让每个人都受益,您通常会创建一个snaplet。在您的情况下,最好利用HDBC snaplet,您可以使用它来连接到sqlite3数据库。
结帐http://norm2782.github.com/snaplet-hdbc.html以获得有关使用HDBC snaplet的优秀教程。