Snap: скомпилированное соединение, зависящее от решения во время выполнения и переменной URL
У меня есть ситуация, когда мне нужно создавать скомпилированные соединения и подавать в них данные, которые зависят от переменной URL. Я борюсь за решение проблемы.
Таким образом, существует простой список имен файлов, который необходимо отобразить в таблице. Просто. Файлы принадлежат группе или категории, поэтому вы можете перечислить все файлы или связанные с определенной категорией. Я извлекаю данные, используя эту функцию:
getFilesList :: Maybe ByteString -> AppHandler [Document]
getFilesList cat = do
let selection = maybe [] (\c -> ["category" =: T.decodeUtf8 c]) cat
r <- eitherWithDB $ rest =<< find (select selection "files") {project = ["blob" =: 0]}
return $ either (const []) id r
Если он ничего не получает, он вытягивает весь список, если он получает категорию Just, он извлекает файлы, которые принадлежат этой категории. Пока все просто.
Я вызываю вышеупомянутую функцию из обработчика, чтобы я мог передать ей аргумент.
listFiles :: AppHandler [Document]
listFiles = do
cat <- getParam "cat"
let r = maybe Nothing (\c -> if c == "all" then Nothing else Just c) cat
render "files/list-files"
getFilesList r
Если я получаю "все" или "Ничего" в URL - я получаю полный список. Что-нибудь кроме этого - я получаю отфильтрованный список категорий.
Корень URL выглядит следующим образом
("/files/:cat", method GET listFiles)
Но теперь у меня есть проблема, потому что функция "method" будет принимать только сигнатуру Handler App App (). Мой обработчик возвращает данные для подачи в соединения.
Я строю свои соединения следующим образом:
listFilesS :: Splices (Splice (Handler App App))
listFilesS = "files" ## files
where
files = manyWithSplices runChildren file $ lift listFiles -- Feed data here
file = do
"file-name" ## (pureSplice . textSplice $ at "name")
"file-oid" ## (pureSplice . textSplice $ id)
"file-date" ## (pureSplice . textSplice $ dateFromDoc)
"file-size" ## (pureSplice . textSplice $ fsize)
"file-type" ## (pureSplice . textSplice $ at "type")
"file-auth" ## (pureSplice . textSplice $ const "admin")
"file-link" ## (pureSplice . textSplice $ flink)
"file-category" ## (pureSplice . textSplice $ at "category")
where id = T.pack . show . valueAt "_id"
fsize = T.pack . show . round . (flip (/) 1024) . (at "size")
flink = T.append "/files/" . id
Я не могу найти способ обойти это. Наверное, просто упустил что-то глупое. Есть идеи, что я делаю не так?
В любом случае, моя функция-обработчик выглядит неправильно, так как я сначала отображаю шаблон, а затем извлекаю данные. Если я исправлю обработчик, я не смогу подать данные на основе параметра URL.
Смущенный.
1 ответ
Прежде всего, если listFiles только что вернулся [Document]
тогда ты не хочешь звонить render "files/list-files"
, Таким образом, первый заказ - полностью устранить эту черту. Вы можете спросить, почему. Это подводит нас ко второму пункту. Ваш маршрут должен выглядеть так:
("/files/:cat", method GET $ render "files/list-files")
Ваш маршрут является результатом рендеринга шаблона. Это почти всегда так с маршрутами Heist. Иногда вы можете явно render
, В других случаях вы можете просто использовать маршруты, автоматически предоставленные вам heistServe
,
Я не могу комментировать listFilesS
не видя больше кода для Document
API, но выглядит разумно. Предполагая, что он работает должным образом, вам просто нужно связать это соединение для вашего приложения примерно так:
addConfig heist $ mempty { hcCompiledSplices = listFilesS }
Затем просто используйте тег files в вашем шаблоне "files/list-files".