Elm でランダムにテキストを表示させる(その 2)

先日から作っていた web アプリが一応できた。

こういうスプレッドシートに文章を入力して、こういうサイトでランダムに表示させる、というもの。(何に使うものなのかは雰囲気で察してもらえればと)

Google スプレッドシートからは JSON でデータを吐くことができる(GET でのリクエストに対応するための関数が用意されている)ので、そちらは特筆すべきことなし。

下記記事のサンプルを参考にして、サクッと書いた。

変更したのはシート C 列 enabled のチェックがオフになっている行は除外する点と、選択したシートではなく全シートを対象とした点かな。

/**
 * Sheet から object にする
 * @param {Object} sheet
 * @param {Object}
 */
function convertFromSheet(sheet) {
    var rows = sheet.getDataRange().getValues();
    var keys = rows.splice(0, 1)[0];

    // filetering
    rows = rows.filter(function (row) {
        // enabled == true
        return row[2] === true;
    });

    var result = {};
    result["sheetName"] = sheet.getName();
    result["rows"] = rows.map(function (row) {
        var obj = {};
        row.map(function (item, index) {
            obj[String(keys[index])] = String(item);
        });
        return obj;
    });
    return result;
}

/**
 * 各シートのデータを filter した上で object にする
 * @returns {Object}
 */
function getObjectFromSheets() {
    const sheets = SpreadsheetApp.getActive().getSheets();
  return { sheets : sheets.map(convertFromSheet) };
}


/**
 * web app として公開する
 */
function doGet(e) {
    const data = getObjectFromSheets();
    return ContentService.createTextOutput(JSON.stringify(data, null, 2))
        .setMimeType(ContentService.MimeType.JSON);
}

で、Elm ですよ。

汎用的なプログラミング言語ではなく、Web のフロントエンドを作ることに特化した言語。Dart とかもそういう感じなのかな?知らないけれど。 コンパイルして html を出力したり、JS を出力したりできる。

# html
$ elm make src/Main.elm --output=index.html

# js
$ elm make src/Main.elm --output=elm.js

静的型付けで型の不一致をすぐ教えてくれるのがよい、ということを少し Twitter で書いたけれど、それに加えて、言語とフレームワークが一体となっていてプログラムの構成などで迷う必要がないのもいいところ。

細かいところについては各種ノウハウなどあるだろうけれど、大枠では Elm way に乗っかっていけばよくて、他の人も同じ構成でやっているからブログ記事なども参考にしやすかった。

OCamlHaskell に興味を持っていて少しだけかじったこともあった(歯型がついたかどうかくらいのレベルだけれど)ので、文法などはそんなに苦労せず理解できた。あと最近出たばかりの書籍があって丁寧に解説されていてわかりやすかったな。公式のガイド An Introduction to Elm も何回も読んだっけ。

基礎からわかる Elm

基礎からわかる Elm

あと、こうやってパイプライン演算子 |> を使ってすっきり書けると気分が良い。

addLineBreak : String -> List (Html Msg)
addLineBreak note =
    String.lines note
        |> List.map text
        |> List.intersperse (br [] [])

もう少し何か書こうと思っていたのだけれど、ひとまずこの辺で。