Я пытаюсь понять простую конструкцию с защелкой.
Кроме того, когда мне на самом деле нужно сделать снимок, а когда простую боковую библиотеку?
И если мне нужен один, как мне сделать это из библиотеки?
Например, у меня есть несколько функций БД, где я оборачиваю свой код 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
Каждая функция инициирует новое соединение и закрывает соединение после фиксации.
Я полагаю, что создание моментальных снимков - это способ избежать соединения в каждой функции?
В моем обработчике я бы использовал это так:
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
}
Пока это работает. Мой вопрос (ы):
Когда мне действительно нужно превратить библиотеку в брелок? Нужно ли мне превращать мою простую библиотеку БД в брелок, чтобы инициализировать соединение, а не устанавливать соединение в каждой функции?
Теперь, если я сделаю снимок ...
На веб-сайте Snap есть крошечный пример sanaplet верхнего уровня, но нет никаких следов того, как создать собственный простой плаглет.
Итак, я добавил функцию инициализации моментального снимка в мою библиотеку БД.
dbInit :: SnapletInit b Connection
dbInit = makeSnaplet "DB" "My DB Snaplet" Nothing $ do
dbc <- liftIO $ connectSqlite3 "/somepath/db.sqlite3"
onUnload $ disconnect dbc
return $ dbc
Это правильный способ сделать это? Это все, что мне нужно, чтобы превратить его в съемную заглушку?
Затем я складываю этот моментал БД в основное приложение
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)? Является ли это в общем правильное направление для создания простого щелчка? Мне действительно нужна кнопка в моем случае?
Спасибо.