在Elm中使用新数据更新嵌套记录

时间:2018-10-29 16:19:36

标签: list immutability record elm

我有两个JSON,它们已成功按顺序解码。我想使用新的html_fragment并更新现有的html_fragment。通常这很简单,但是我的数据结构给我带来了困难:

type PostDataContainer
    = PostDataContainer PostData


type alias PostData =
    { title : String
    , comments : List Comment
    }


type alias Comment =
    { comment_id : Int
    , html_fragment : String
    }


type alias CommentHtml =
    { id : Int
    , html_fragment : String
    }

我刚得到CommentHtml,并想更新html_fragment中现有的Comment。这是我到目前为止的内容:

    MergeCommentHtml commentHtmlData ->
        case commentHtmlData of
            Err err ->
                Debug.log ("Error decoding CommentHtmlData" ++ toString err)
                    ( mdl, Cmd.none )

            Ok commentHtml ->
                case mdl.maybePostDataContainer of
                    Just (PostDataContainer postData) ->
                        let
                            updatedCommentData = -- I dont know how to calculate this?
                        in
                        ( { mdl | postData = { postData | comments = updatedCommentData } }, Cmd.none )

请注意,这里的commentHtmlList CommentHtml。关于如何使用comment.html_fragment中的新值更新旧的commentHtml的任何想法?

2 个答案:

答案 0 :(得分:2)

选项1: 只需解码数据即可。当需要显示它时,请通过编写的某些功能(如rawJsonDataToNicerData)适当地排列它。

选项2:
假设您实现以下功能:

-- given a new comment, and some PostData, return the new version of the PostData
updateData : CommentHtml -> PostData -> PostData

-- so now, assuming we can decode a CommentHtml with commentHtmlDeocder
-- we can do the following
dataUpdaterDecoder : Decoder (PostData -> PostData)
dataUpdaterDecoder 
   commentHtmlDecoder |> Decoder.andThen (\commentHtml -> updateData commentHtml)

现在无论我们要解码commentHtmlDeocder的什么地方,我们都可以改为解码dataUpdaterDecoder,并使用其中的一些来更新我们的数据。

以下是使用上述想法的关系数据解码器的示例:

https://ellie-app.com/3KWmyJmMrDsa1

答案 1 :(得分:1)

鉴于评论中commentHtmlDataList,我认为最简单的方法是将其转换为以Dict为键的id,然后在在字典中寻找comment_id的现有评论。如果存在,则替换html_fragment,如果不存在,则返回原始的未修改的

let
    commentHtmlDict =
        commentHtmlData
            |> List.map (\c -> (c.id, c))
            |> Dict.fromList

    updatedCommentData =
        postData.comments
            |> List.map (\comment ->
                case Dict.get comment.comment_id commentHtmlDict of
                    Just commentHtml ->
                        { comment | html_fragment = commentHtml.html_fragment }

                    Nothing ->
                        comment
            )