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".

Другие вопросы по тегам