ES6過渡期のMithril入門　⑤MEANスタックAllcountJSをオススメ

#0) 新種MEANスタックでMithril学習を加速。
React以降、一部では死語になりつつあるのかもしれないが、１年前のプチパズワードMEANスタック -MongoDB, Express, AngularJS, Node.js。そんなMEANスタックの新顔(変顔)が、[allcountjs](https://github.com/allcount/allcountjs)。

[Moongiftさんいわく](http://j.mp/moon_allcount):
> AllcountJSでは作法に沿って書くことで、UI/UXに困ることなくリッチなWebアプリケーションが開発できます。

どう困らないのか・なぜ困らないのかなどと、記事に突っ込む前に、
AllcountJSのデモサイトに移動してみる。
https://allcountjs.com/#demo

HTML+CSSを設定するjadeとlessに並んで、アプリケーションを記述するmain.jsペーンがある。
以下のように書き換えると、

```main.js
A.app({
  appName: "プレゼント配送管理",
  appIcon: "heart",
  menuItems: [
    {
      name: "プレゼント",
      icon: "gift",
      entityTypeId: "Present",
    }
  ],
  entities: function(Fields) {
    return {
      Present: {
        title: 'プレゼント',
        fields: {
          item: Fields.text("Item").required(),
          comment: Fields.text("Comment").required(),
          date: Fields.date("Giving Date").required()
        }
      }
    }
  }
});
```

webプログラマならおなじみのCRUDアプリがweb上で動作する:

![present1.png](https://qiita-image-store.s3.amazonaws.com/0/16455/a8d12b5f-6829-fe8e-b241-96b6233bef17.png)

こうした芸当のできるAllcountJSのソースコードを眺めていて、これは、MithrilJS学習に使いどころ大と気がついた。

#1)　ローカル環境に導入
## allcountjsの導入
gulpベースの環境設定がしっかりとなされており、導入は容易。

```zsh
npm install -g allcountjs-cli
cd /your/dev/folder
allcountjs init
# <project_name>等の質問に答える
cd <project_name> && npm install
```
npm installで何が導入されているのかは、
./node_modules/allcountjs
以下のpackage.jsonを眺めると見当がつく(express/angularjsの存在も確認できる。)。

## mongodbの導入
allcountjsの実行にはデータ保存先としてmongodbの設定が必要となるため、入れておく。
手元のPCにはLinux Mintが入っているため、

```
sudo apt-get install mongodb
sudo mkdir -p /data/db
sudo chmod 0755 -R /data/db
mongod --dbpath /data/db
```
あたりで立ち上げる。
allcountjsの実行にmongodb自体の権限設定などは必要ない。

試行錯誤でmongodがロックされてしまったときには、
> rm /data/db/mongod.lock

あたりで 。
(...ほんとに使うときにはmongodbをもう少し丁寧に導入したほうが良いだろう。)

#2) allcountjsアプリを実行

```
$ allcountjs run
Using db url: mongodb://localhost:27017/helloworld-app
{ [Error: Cannot find module '../build/Release/bson'] code: 'MODULE_NOT_FOUND' }
js-bson: Failed to load c++ bson extension, using pure JS version
Failed to fetch "app-config". Trying to use as regular directory.
Application server for "app-config" listening on port 9080
```

c++版のbsonがないと怒られはするが、9080番でアプリが立ち上がる。0)の画面キャプチャにあるようにブラウザ上でデータを入れてみた後、mongoコンソールで、データ格納の様子を確認する。

```mongo.onSh
>show dbs
helloworld-app	0.0625GB
local	0.03125GB
> use helloworld-app
switched to db helloworld-app
> show collections
Integration
Present
User
migrations
system.indexes
> db.Present.find();
{ "item" : "gift v1", "comment" : "v1", "date" : ISODate("2015-11-10T15:00:00Z"), "_id" : ObjectId("563fea827dc2ea77392e6713"), "createTime" : ISODate("2015-11-09T00:36:18.199Z"), "modifyTime" : ISODate("2015-11-09T00:36:18.199Z"), "__textIndex" : [ 	"gift", 	"v1", 	"wed", 	"nov", 	"11", 	"2015", 	"00:00:00", 	"gmt+0900", 	"(jst)" ], "__v" : 0 }
{ "item" : "gift v2", "comment" : "update.", "date" : ISODate("2015-11-25T15:00:00Z"), "_id" : ObjectId("563fea997dc2ea77392e6714"), "createTime" : ISODate("2015-11-09T00:36:41.164Z"), "modifyTime" : ISODate("2015-11-09T00:36:41.164Z"), "__textIndex" : [ 	"gift", 	"v2", 	"update.", 	"thu", 	"nov", 	"26", 	"2015", 	"00:00:00", 	"gmt+0900", 	"(jst)" ], "__v" : 0 }
{ "item" : "プレゼン", "comment" : "トトトトトト", "date" : ISODate("2015-11-18T15:00:00Z"), "_id" : ObjectId("563feab57dc2ea77392e6715"), "createTime" : ISODate("2015-11-09T00:37:09.343Z"), "modifyTime" : ISODate("2015-11-09T00:37:09.343Z"), "__textIndex" : [ 	"プレゼン", 	"トトトトトト", 	"thu", 	"nov", 	"19", 	"2015", 	"00:00:00", 	"gmt+0900", 	"(jst)" ], "__v" : 0 }
> db.User.find();
{ "username" : "admin", "passwordHash" : "56ed559cbdec8ff5c03e44817fa885ecf9bdc881", "_id" : ObjectId("563fd9c0f089e8d7336bb543"), "createTime" : ISODate("2015-11-08T23:24:48.557Z"), "modifyTime" : ISODate("2015-11-08T23:24:48.557Z"), "__textIndex" : [  "admin",  "56ed559cbdec8ff5c03e44817fa885ecf9bdc881" ], "roles" : [  "admin" ], "__v" : 0 }

```
確かにデータがmongodbのPresentコレクションに投入されている。また、Userコレクションも作成されていて、adminユーザーが設定済であることも分かる。allcountjsのドキュメントを参考するに、ユーザー管理もデータへの権限設定も簡単に書けるよう、すでに作りこまれている模様。
https://allcountjs.com/docs/apps

#3)allcountjsの使いどころを考える。
Railsがまだ新しかった10年前ならば、自動CRUDヒャッホー、となるのだろうが、
既に似たようなものを何度か触った気がするので、2015年ならではの使い方を考える。

## ①社内アプリ開発向け

開発チームは、allcountjsを業務アプリ開発向けとして推したい模様だ。
*(ロシア語圏のチームらしく、[allcountjsベースのCRMのアピール](http://habrahabr.ru/company/allcountjs/blog/270119/)をロシア語で先週出している。
REST APIも切られるよ、とか、雰囲気はつかめる。)*
また、[Herokuには、１クリックでCRMをデプロイできるよ、](http://j.mp/allcrmheroku)とのことで、MEANスタックの最新作として、アプリ立ち上げの速さをアピール。自社事業所間での情報共有アプリなどをsuper easyに作れるのではないだろうか(フロントエンドエンジニアならば、気合入れれば、週末でそこそこのアプリがリリースできることだろう)。

ロシア語圏発ということで、ロケールもすでに導入されている。

```messages_ru.js
module.exports = {
    "entity.backToList": "Назад к списку",
    "entity.create": "Создать",
    "entity.done": "Готово",
    "entity.edit": "Изменить",
    "entity.search": "Поиск",
    "entity.noRecords": "Нет записей",
    "Back to list": "Назад к списку",
    "Create": "Создать",
    "Done": "Готово",
    "Search": "Поиск",
(略)
    "Yes": "Да",
    "No": "Нет",
    "Not set": "Не задано",
    "Sign Up": "Зарегистрироваться",
    "Repeat Password": "Повторите пароль",
    "User with provided user name already exists": "Пользователь с таким именем уже существует",
    "Are you sure you want to delete it?": "Вы уверены, что хотите удалить эту запись?"
};
```
日本語化も、複数言語対応も難しくないと思われる。


##②SPA志向のJSフレームワークの学習用途（REST API）。

allcountjsは、ディフォルトで、REST APIが切られている。例えば、HTTP GET:

```
> curl http://localhost:9080/api/entity/Present
[{"item":"プレゼン","comment":"トトトトトト","date":"2015-11-19","id":"563feab57dc2ea77392e6715"},{"item":"gift v2","comment":"update.","date":"2015-11-26","id":"563fea997dc2ea77392e6714"},{"item":"gift v1","comment":"v1","date":"2015-11-11","id":"563fea827dc2ea77392e6713"}]
```

シングルページアプリ(SPA)用途で、Mithrilを学んでいる身として，これはかなりありがたい。
Node/Expressの設定とかをスキップして、Mithrilから即座にmongodbにアクセスできるようになるわけだから。

このRESTをプロトタイピングに用いて、本番では、RESTの部分を得意なWAFで気合入れて書く、というのが良い気がする。
*-- 数年後のクロスプラットフォームSPAとして[sri推ししたい自分](http://qiita.com/kmry2045/items/a39685c5cca6969c32aa)は、本番アプリは、scalaかkotlinで書く。*


#4) Да,Обязательное！

（訳 : イエス、これは(僕に)必要なものだ！*...ロシア語ロケールをコピペ...*）

気に入ったので、次回以降のMithril学習のフロントエンドにallcountjsを用いることとする ;)