在Yesod Persist模型中存储Markdown [英] Storing Markdown in a Yesod Persist Model

查看:98
本文介绍了在Yesod Persist模型中存储Markdown的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在一个带有MySQL后端的持久模型的字段中存储降价。我将用例分解为:

模型:

  TestModel 
content Markdown

Model.hs:

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

这似乎创建了正确的迁移:

 的MySQL>显示test_model中的列; 
+ --------- + ------------ + ------ + ----- + --------- + ---------------- +
|字段|类型|空| Key |默认|额外|
+ --------- + ------------ + ------ + ----- + --------- + ---------------- +
| id | bigint(20)| NO | PRI | NULL | auto_increment |
|内容|文字| 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]
***异常:runFakeHandler问题:InternalErrorget TestModelKey {unTestModelKey = SqlBackendKey {unSqlBackendKey = 2}}:字段内容:不是PersistText值

我的第一个猜测是TestModel构造函数的值是错误的,但即使在使用创建对象时也会发生相同的错误。 markdownField 形式:

  testModelForm :: AForm Handler TestModel 
testModelForm = TestModel
< $> areq markdownFieldContentNothing

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}}:字段内容:不是PersistText的值@(yesod-core-1.4.12:Yesod.Core.Class.Yesod ./Yesod/Core/Class/Yesod .hs:577:5)

以前有谁看过这个异常并知道如何处理它?我发现这个错误的唯一文档是源代码 for yesod-text-markdown

解决方案原因是 persistent-mysql 包中的一个bug现在已经在 persistent-mysql中修复了-2.3



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

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



我在#451 ,通过检查该列的字符集,MySQL API文档建议将其作为适当的解决方案。



有关更多详细信息,请参阅请求或此问题



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


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.

解决方案

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.

这篇关于在Yesod Persist模型中存储Markdown的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆