2016-11-26 4 views
1

Я столкнулся с интересной проблемой, которая, по моему мнению, может быть подходящим местом для Template Haskell. Я работаю над веб-интерфейсом базы данных, используя yesod и yesod-persistant. Я генерирую свои типы баз данных, используя функцию mkPerist и квазициклер persistLowerCase. Моя проблема в том, что мне нужен способ редактировать поля базы данных, но запись кода группы для шести разных страниц для каждого из столбцов кажется невероятно повторяющейся. Я решил, что могу использовать Template Haskell для автоматического создания текстовых полей и флажков для редактирования этого столбца базы данных с учетом типа. В идеале я просто передал бы имя типа функции Template Haskell, а затем TH позаботился бы о создании всего Гамлета для этой страницы. Мой вопрос: могу ли я использовать шаблон Haskell в этом случае? Это лучшее решение? В частности, может ли шаблон Haskell генерировать код для других квазициклов? В частности, Гамлет? Вот ссылка на мой проект на данный момент: https://github.com/ProspectRidgeTech/PRADatabase Спасибо заранее! (PS. Дайте мне знать, если есть лучший способ подойти к этой проблеме, и если у вас есть какие-либо предложения по моему вопросу.)Могу ли я использовать шаблон Haskell для генерации кода Гамлета?

ответ

1

Чтобы ответить на ваш вопрос: Да, вы можете, однако я бы не рекомендовал его. Квази Цитатник это просто функция, которая взять строку и сгенерировать код, так что вы, когда вы видите

[hamlet|blah blah|] 

Вы можете заменить его (или эквивалент)

$(hamlet "blah blah") 

Так что ничто не мешает вам в TH для генерации строки в дереве вызовов. Однако одна из точек TH - безопасность типа. Создание строки для последующего разбора вида поражения объекта. Кроме того, эта генерация кода из 2 шагов, вероятно, будет трудно отлаживать.

В любом случае, если ваша проблема заключается в генерации таблицы для постоянных объектов, я не думаю, что вам нужно TH вообще и просто используйте информацию о постоянных полях. У меня была аналогичная проблема, и я написал код, который генерирует таблицу Html для списка объектов. Это не должно быть сложно изменить.

entitiesToTable :: PersistEntity a => (FieldDef -> Text) -> [Entity a] -> Html 
entitiesToTable getColumn entities = do 
    let eDef = entityDef (map entityVal entities) 
    [shamlet| 
<table.table.table-bordered.table-striped class="#{unHaskellName $ entityHaskell eDef}"> 
    <tr> 
    <th> Id 
    $forall field <- entityFields eDef 
     <th> #{getColumn field} 
    $forall Entity eit entity <- entities 
    <tr> 
     <td.id> #{renderPersistValue $ toPersistValue eit} 
     $forall (pfield, fieldDef) <- zip (toPersistFields entity) (entityFields eDef) 
     <td class="#{getHaskellName fieldDef}" > #{renderPersistValue $ toPersistValue pfield} 
|] 

Написание кода для обработки формы и обновления базы данных может быть более сложным и нужно TH, однако не Гамлет участвует в этом шаге.

+0

Спасибо! Я думаю, что если я смогу решить хотя бы часть этой проблемы без TH, это, безусловно, способ ее решения! Я не знал, что Persistent предоставил такую ​​информацию типа! В качестве быстрого последующего вопроса, откуда берется параметр 'getColumn'? Я предполагаю, что могу сделать что-то вроде '(runDB $ selectList [] [])', чтобы получить список всех «сущностей» из определенного столбца, но что делает '(FieldDef -> Text)'? Кроме того, вы могли бы связать меня с модулем, где определены эти постоянные функции? Спасибо за вашу помощь! – thelostlambda

+0

'getColumn :: FieldDef -> Text' - это просто функция, которая извлекает имя из определения столбца, чтобы использовать его для имени столбца. Я лично использую 'unDBName. fieldDB', но вы можете изменить, например, изменить случай. – mb14

+0

[там] (https://hackage.haskell.org/package/persistent-2.6/docs/Database-Persist-Types.html) – mb14

Смежные вопросы