【问题标题】:Is Form Field conversion possible in yesod?是否可以在 yesod 中进行表单字段转换?
【发布时间】:2012-06-29 11:14:59
【问题描述】:

是否可以将 checkM 改为以下类型:

checkM :: RenderMessage master msg => 
          (a -> GHandler sub master (Either msg b)) -> 
          Field sub master a -> Field sub master b

原因如下:

我有一个要求输入用户名的表单。使用 checkM,我立即在数据库中查找输入的用户是否存在:

userField = checkM userexists textField
userexists input = do
  mbuser <- runDB $ getBy $ UniqueName input
  return $ case mbuser of
    Nothing  -> Left ("This user does not exist!" :: Text)
    (Just (Entity uid _)) -> Right input 
    -- I would like to write "return Right uid" above!

但是,我只能返回 input::Text,所以在表单接受用户输入后,我需要再次查找同名的数据库以获取该用户的数据库密钥,这才是我真正想要的想要。

(这个例子在很大程度上被简化了。本质上,我想获取一系列不同用户输入的数据库键(都在一个表单中),我只能作为 TextFields 询问,或者不能?)

【问题讨论】:

    标签: haskell yesod


    【解决方案1】:

    类型签名看起来如此的原因是Field 有两个方面:如何解析它,以及如何呈现它。 checkM 仅更改解析字段的方式,但渲染函数 (fieldView) 保持不变。因此,值需要保持相同的类型。

    我能想到的获得您想要的行为的最简单方法是拥有一个函数,该函数可以从新类型的值中获取旧类型的值。这样,给定一个新值,我们可以将该函数应用于它并获取旧值以进行渲染。下面是代码的样子:

    checkM' :: RenderMessage master msg
            => (a -> GHandler sub master (Either msg b))
            -> (b -> a)
            -> Field sub master a
            -> Field sub master b
    checkM' f inv field = field
        { fieldParse = \ts -> do
            e1 <- fieldParse field ts
            case e1 of
                Left msg -> return $ Left msg
                Right Nothing -> return $ Right Nothing
                Right (Just a) -> fmap (either (Left . SomeMessage) (Right . Just)) $ f a
        , fieldView = \i n a eres req -> fieldView field i n a (fmap inv eres) req
        }
    

    因此,在您的情况下,您可以通过将userexists 中的最后一行更改为:

    (Just (Entity uid _)) -> Right (input, uid)
    

    然后将userField定义为

    userField = checkM' userexists fst textField
    

    我认为像 checkM 这样的函数可以包含在 yesod 形式中,但希望有一个更好的名称 ;)。

    【讨论】:

    • 谢谢!但是,我想知道我是否做错了什么,因为我似乎总是需要这个 checkM'。例如,我想通过表单读取 int 值列表。该列表可以具有任意长度(例如 oeis.org)。我将再次从一个 textField 开始,现在使用这个 checkM' 来验证它确实是一个格式良好的整数列表。将解析放到字段中真的有意义吗,还是应该将这段代码更好地包含在其他地方?
    • (PS: 甚至不需要 checkM',而是在 int list 示例中使用 check',因此非常快速地从一个可以解析值的函数生成任何类型的字段似乎需要一个文本(文本 - > 任一 msg a),但由于它不存在,我只是想知道我做错了什么。)
    • 我不确定你在这里问的是什么,但即使有一个 Ints 列表,你也需要处理第二次渲染。
    猜你喜欢
    • 2011-06-16
    • 1970-01-01
    • 2011-04-01
    • 1970-01-01
    • 2015-12-22
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    相关资源
    最近更新 更多