Storing Markdown in a Yesod Persist Model

删除回忆录丶 提交于 2019-12-10 19:04:17

问题


I am trying to store markdown in a field on a Persistent model with a MySQL backend. I've broken the use case down to:

models:

TestModel
    content Markdown

Model.hs:

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

This seems to create the correct migrations:

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

However when I try to retrieve data from this table, I'm presented with an exception. The example below is from a cabal repl but the same happens when the application is running:

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"

My first guess was that the value for the TestModel constructor was wrong, but the same error occurs even when creating the object using a markdownField in a form:

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)

Has anybody seen this exception before and know how to handle it? The only documentation of this error I could seem to find was the source code for yesod-text-markdown.


回答1:


This turned out to be caused by a bug in the persistent-mysql package that's now fixed in persistent-mysql-2.3.

Here's the root cause for those interested:

The MySQL C library (and by extension the Haskell mysql package, which persistent-mysql depends on) doesn't distinguish between binary and textual data at the type level. So if you saved a TEXT value to the database, when it was looked it up by persistent it appeared to be binary data (a PersistByteString).

I fixed this in #451 by checking the character set of the column, which the MySQL API docs recommend as the appropriate solution.

For more details, see that pull request or this issue.

Thanks for asking this question; I wouldn't have realized there was a bug otherwise.



来源:https://stackoverflow.com/questions/31898691/storing-markdown-in-a-yesod-persist-model

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!