分解出控制器动作

Factoring out controller actions

上下文

这是 IHP 指南 blog example 中的 PostsController

instance Controller PostsController where
    action PostsAction = do
        posts <- query @Post
            |> orderByDesc #createdAt
            |> fetch
        render IndexView { .. }

    action NewPostAction = do
        let post = newRecord
        render NewView { .. }

    action ShowPostAction { postId } = do
        post <- fetch postId
            >>= pure . modify #comments (orderByDesc #createdAt)
            >>= fetchRelated #comments 
        render ShowView { .. }

    action EditPostAction { postId } = do
        post <- fetch postId
        render EditView { .. }

    action UpdatePostAction { postId } = do
        post <- fetch postId
        post
            |> buildPost
            |> ifValid \case
                Left post -> render EditView { .. }
                Right post -> do
                    post <- post |> updateRecord
                    setSuccessMessage "Post updated"
                    redirectTo EditPostAction { .. }

    action CreatePostAction = do
        let post = newRecord @Post
        post
            |> buildPost
            |> ifValid \case
                Left post -> render NewView { .. } 
                Right post -> do
                    post <- post |> createRecord
                    setSuccessMessage "Post created"
                    redirectTo PostsAction

    action DeletePostAction { postId } = do
        post <- fetch postId
        deleteRecord post
        setSuccessMessage "Post deleted"
        redirectTo PostsAction

分解一个动作

假设我有一个控制器,其中一个动作定义变得非常长,我想将它放在一个单独的文件中。

举个例子,我们试着把这个移出来:

action PostsAction = do
    posts <- query @Post
        |> orderByDesc #createdAt
        |> fetch
    render IndexView { .. }

我尝试设置一个单独的独立函数:

actionPostsAction = do
    posts <- query @Post
        |> orderByDesc #createdAt
        |> fetch
    render IndexView { .. }

那么我的动作定义可以是:

action PostsAction = actionPostsAction

但是,当我设置独立函数时,我在 vscode:

中报告了一些错误

问题

分解动作的好方法是什么?有办法吗?

该指南有一节是关于 Controller & Actions 的,但我没有注意到任何关于拆分操作的内容。如果我在那里遗漏了什么或者是否有另一个地方谈论这个,请告诉我。

我认为这是需要显式类型签名的情况之一,这应该可行:

actionPostsAction
  :: ( ?context      :: ControllerContext
     , ?modelContext :: ModelContext
     , ?theAction    :: PostsController
     )
  => IO () 
actionPostsAction = do
    posts <- query @Post
        |> orderByDesc #createdAt
        |> fetch
    render IndexView { .. }

另请参阅:https://ihp.digitallyinduced.com/Guide/troubleshooting.html#unbound-implicit-parameter-modelcontextmodelcontext