##はじめに
正直言ってこれはバッドノウハウなんじゃないかと個人的に思ってるので、もっといい方法があったり、いやこれでいいってなことがあったらコメントで教えていただきたく……
##困ったこと
YesodにはApplicative FormやMonadic Formといったモデルを指定すればほとんどのフォーム関連の処理をよしなにしてくれるという素敵な機能がありますが、フォームの定義時にモデル内のすべてのフィールドを何らかの形でフォームにすることを要求されます。ということは、モデル内にユーザには表示したくない隠しフィールドみたいなのが存在するとそれも何らかの形でフォームの中に生成しないといけないような感じになってしまいます。
たとえば、Modelないでこのように定義されたモデルがあったとします。
Model
something Text
hidden Bool
フォームはこんな感じにします。すると、秘密にしておきたいBoolのフィールドも丸見えになってしまいます……
addMemberForm affiliations extra = do
(firstNameResult, firstNameView) <- mreq textField "なんか" Nothing
(hiddenResult, hiddenView) <- mreq boolField "秘密のBool" Nothing --これを表示したくないけどユーザ側の変更では常時Falseになっててほしい
let result = Member
<$> firstNameResult
<*> hiddenResult
widget = $(widgetFile "template")
return (result, widget)
最初にフォームの中でそのフィールドを埋め込まなければいいのかなと思ったのですが、そうするとPostで値を送信した時に初期値になる値が欠落してしまってダメっぽいので諦めました。
##若干怪しい解決
しょうがないのでこのように解決しました。
Yesodのフィールドのソースを読んで、その真似をした常時Boolを返すフィールドを作る
alwaysFalseField :: Monad m => RenderMessage (HandlerSite m) FormMessage => Field m Bool
alwaysFalseField = Field
{ fieldParse = \_ _ -> return $ Right $ Just False
, fieldView = \_ _ _ _ _ -> [whamlet| |]
, fieldEnctype = UrlEncoded
}
そして、さっきの秘密のフィールドを定義するときにこのフィールドを使いました。
(hiddenResult, hiddenView) <- mreq alwaysFalseField "秘密のBool" Nothing --これを表示したくないけどユーザ側の変更では常時Falseになっててほしい
一応この方法で常時初期値を返す秘密のフォームを作ることは出来ました。しかしこれがいい方法とも思えないのでご指摘お待ちしています……