LoginSignup
3
2

More than 5 years have passed since last update.

ElmのパッケージサイトのSessionを参考にして試したメモ

Posted at

概要

package.elm-lang.orgを参考に、一度取得したデータを保持して再取得しない仕組みを試した。
もともとはマークダウンを取得して表示する処理。
一度取得したものは取得しない処理を追加。

ソースの変更点についてメモ

Session.elm

package.elm-lang.orgは author project versionをディレクトリのキーにしていたので、
こちらはマークダウンのファイル名とバージョンで一意にするようにする。
マークダウンはほぼ更新しない予定なのでバージョンはオマケ。

Session.elm
module Session exposing (Data, Version, addMarkdown, empty, fetchMarkdown, getMarkdown, markdownUrl, toMarkdownKey)

import Dict
import Http
import Json.Decode as Decode
import Url.Builder as Url


type alias Version =
    Float



-- SESSION DATA


type alias Data =
    { markdowns : Dict.Dict String String
    }


empty : Data
empty =
    Data Dict.empty



-- Markdown


toMarkdownKey : String -> Version -> String
toMarkdownKey fileName version =
    fileName ++ "@" ++ String.fromFloat version


getMarkdown : Data -> String -> Version -> Maybe String
getMarkdown data fileName version =
    Dict.get (toMarkdownKey fileName version) data.markdowns


addMarkdown : String -> Version -> String -> Data -> Data
addMarkdown fileName version markdown data =
    let
        newMarkdowns =
            Dict.insert (toMarkdownKey fileName version) markdown data.markdowns
    in
    { data | markdowns = newMarkdowns }


fetchMarkdown : (Result Http.Error String -> msg) -> String -> Cmd msg
fetchMarkdown toMsg fileName =
    Http.get
        { url = markdownUrl fileName
        , expect = Http.expectString toMsg
        }


markdownUrl : String -> String
markdownUrl fileName =
    Url.absolute [ "assets", "markdown", fileName ] []

Page/Markdown.elm

Sessionとバージョンをモデルに追加している。

Page/Markdown.elm
 import Markdown
+import Session
 import Skeleton exposing (viewLink, viewMain)
Page/Markdown.elm
 type alias Model =
-    { fileName : String
+    { session : Session.Data
+    , fileName : String
+    , version : Session.Version
     , state : State
     , naviState : NaviState
     }

initでセッションとバージョンを引数に追加。
また、セッションにデータがあるか問い合わせる処理を追加。
なければ変更前と同様にHttpから取得する。

Page/Markdown.elm
-init : String -> ( Model, Cmd Msg )
-init fileName =
-    ( Model fileName Init Close
-    , getMarkdown GotMarkdown fileName
-    )
+init : Session.Data -> String -> Session.Version -> ( Model, Cmd Msg )
+init session fileName version =
+    case Session.getMarkdown session fileName version of
+        Just markdown ->
+            let
+                model =
+                    Model session fileName version (Loaded markdown) Close
+            in
+            ( model
+            , Cmd.none
+            )
+        Nothing ->
+            -- ページの初期化
+            -- 最初のModelを作ると同時に、ページの表示に必要なデータをHttpで取得
+            ( Model session fileName version Init Close
+            , Session.fetchMarkdown GotMarkdown fileName
+            )

updateでは、取得したデータをセッションにいれる処理を追加。

Page/Markdown.elm
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    --- init での Http リクエストの結果が得られたら Model を変更する
    case msg of
     case msg of
         GotMarkdown (Ok markdown) ->
-            ( { model | state = Loaded markdown }, Cmd.none )
+            ( { model
+                | state = Loaded markdown
+                , session = Session.addMarkdown model.fileName model.version markdown model.session
+              }
+            , Cmd.none
+            )
        GotMarkdown (Err err) ->
            ( { model | state = Error err }, Cmd.none )

Main.elm

Main.elm
 import Route exposing (..)
+import Session
 import Skeleton exposing (Details, view)

exitで、ページ遷移時にセッションを引き継ぐ処理を行っている。
ここでは暫定的に、マークダウンのページ間でのみセッションを引き継ぐ。
後に、package.elm-lang.orgのように、すべてのページのモデルにsessionをくみこむ予定。

Main.elm
+exit : Model -> Session.Data
+exit model =
+    case model.page of
+        MarkdownPage m ->
+            m.session
+
+        _ ->
+            Session.empty


 goTo : Maybe Route -> Model -> ( Model, Cmd Msg )
 goTo maybeRoute model =
+    let
+        session =
+            exit model
+    in
     case maybeRoute of
         Nothing ->
             ( { model | page = NotFound }

引数にセッションとバージョンを追加。

Main.elm
         Just Route.PrivacyPolicy ->
             let
                 ( markdownModel, markdownCmd ) =
-                    Markdown.init "privacy-policy.md"
+                    Markdown.init session "privacy-policy.md" 1.0
             in
             ( { model | page = MarkdownPage markdownModel }
             , Cmd.map MarkdownMsg markdownCmd
            )
         Just Route.About ->
             let
                 ( markdownModel, markdownCmd ) =
-                    Markdown.init "about.md"
+                    Markdown.init session "about.md" 1.0
             in
             ( { model | page = MarkdownPage markdownModel }
             , Cmd.map MarkdownMsg markdownCmd
            )
         Just Route.Agreement ->
             let
                 ( markdownModel, markdownCmd ) =
-                    Markdown.init "agreement.md"
+                    Markdown.init session "agreement.md" 1.0
             in
             ( { model | page = MarkdownPage markdownModel }
             , Cmd.map MarkdownMsg markdownCmd
            )

変更前のソース

変更後のソース

参考

package.elm-lang.org

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2