シンプルなスナップレットの構造を理解しようとしています。また、実際にスナップレットを作成する必要があるのはいつですか?また、単純なサイド ライブラリはいつ作成する必要がありますか? また、ライブラリが必要な場合は、どうすればライブラリから作成できますか?
たとえば、以下のように SQL コードをラップする一連の DB 関数があります。
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
すべての関数は新しい接続を開始し、コミット後に接続を閉じます。スナップレットを作成することは、すべての機能で接続を回避する方法だと思いますか? 私のハンドラーでは、次のように使用します。
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
}
これまでのところ動作します。私の質問は次のとおりです。実際にライブラリをスナップレットに変更する必要があるのはいつですか? すべての関数で接続を確立するのではなく、接続を初期化するためだけに、単純な DB ライブラリをスナップレットに変換する必要がありますか?
さて、スナップレットを作成すると... Snap の Web サイトには、トップレベルのサナプレットの小さな例がありますが、独自の単純なプラグブル スナップレットを作成する方法の痕跡はありません。
そこで、スナップレットの初期化関数を DB ライブラリに追加しました
dbInit :: SnapletInit b Connection
dbInit = makeSnaplet "DB" "My DB Snaplet" Nothing $ do
dbc <- liftIO $ connectSqlite3 "/somepath/db.sqlite3"
onUnload $ disconnect dbc
return $ dbc
これは正しい方法ですか?プラグ可能なスナップレットに変換するために必要なのはこれだけですか?
次に、この DB スナップレットをメイン アプリにスタックします。
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
}
これはうまくいかないようです。私は何を間違っていますか?これは、スナップレット ハンドル (dbcon) から接続を抽出する正しい方法ですか? これは一般的に、単純なスナップレットを作成する正しい方向ですか? 私の場合、ここで実際にスナップレットが必要ですか?
ありがとう。