在Yesod持久模型中存储Markdown

时间:2015-08-08 21:17:20

标签: haskell markdown yesod persist

我试图在带有MySQL后端的Persistent模型的字段中存储markdown。我已将用例分解为:

模型:

TestModel
    content Markdown

Model.hs:

import Text.Markdown (Markdown)
import Yesod.Text.Markdown ()
....

这似乎可以创建正确的迁移:

mysql> show columns in test_model;
+---------+------------+------+-----+---------+----------------+
| Field   | Type       | Null | Key | Default | Extra          |
+---------+------------+------+-----+---------+----------------+
| id      | bigint(20) | NO   | PRI | NULL    | auto_increment |
| content | text       | NO   |     | NULL    |                |
+---------+------------+------+-----+---------+----------------+

但是,当我尝试从此表中检索数据时,我遇到了一个例外。下面的示例来自cabal repl,但在应用程序运行时会发生同样的情况:

repl> testid <- db $ insert $ TestModel $ Markdown "# Hello world"
[Debug#SQL] INSERT INTO `test_model`(`content`) VALUES(?); [PersistText "# Hello world"]
repl> testmodel <- db $ get testid
[Debug#SQL] SELECT `content` FROM `test_model` WHERE `id`=?; [PersistInt64 2]
*** Exception: runFakeHandler issue: InternalError "get TestModelKey {unTestModelKey = SqlBackendKey {unSqlBackendKey = 2}}: field content: Not a PersistText value"

我的第一个猜测是TestModel构造函数的值是错误的,但即使在表单中使用markdownField创建对象时也会出现相同的错误:

testModelForm :: AForm Handler TestModel
testModelForm = TestModel
        <$> areq markdownField "Content" Nothing

getTestModelR :: TestModelId -> Handler Html
getTestModelR testModelId = do
    testmodel <- runDB $ get404 testModelId
....
08/Aug/2015:12:44:33 -0700 [Error#yesod-core] get TestModelKey {unTestModelKey = SqlBackendKey {unSqlBackendKey = 2}}: field content: Not a PersistText value @(yesod-core-1.4.12:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod.hs:577:5)

之前是否有人见过此例外并知道如何处理它?我似乎找到的这个错误的唯一文档是yesod-text-markdown的{​​{3}}。

1 个答案:

答案 0 :(得分:1)

原来这是由于persistent-mysql中已修复的persistent-mysql-2.3包中的错误引起的。

以下是感兴趣的人的根本原​​因:

MySQL C库(以及mysql所依赖的Haskell persistent-mysql包扩展)并不区分类型级别的二进制和文本数据。因此,如果您将TEXT值保存到数据库,那么当它被持久查找时,它似乎是二进制数据(PersistByteString)。

我通过检查列的字符集在#451中修复了这个问题,MySQL API文档建议将其作为适当的解决方案。

有关详情,请参阅拉取请求或this issue

感谢您提出这个问题;我不会意识到还有一个错误。