Fragmentaの覚書き


あらまし

会社の方針でGo言語を始めました。
手っ取り早くイイ書き方を覚える為に、何かオープンソースのプロダクトを読んでみよう、と、慣れているところでCMS辺りを探してみたところ・・・Fragmentaというものを見つけました。
というか、それしか見つからなかったので試してみる事にしました。

ちなみに、執筆時のバージョンは1.5rcです。

Fragmentaとは?

golang製のCMSのようです。
ただ、内容を見るとアプリケーションを作るフレームワークとして使用される事も意識しているようです。

セットアップ

前回の続きなので、引き続いてcloud9で試しています。

ドキュメントがありますが、今のところ正確で無いようですので、試してみた手順を思い出しながら書いていきます。

インストール

$ go get -u github.com/fragmenta/fragmenta
$ fragmenta help
------
Fragmenta version: 1.5rc
  fragmenta version -> display version
  fragmenta help -> display help
  fragmenta new [app|cms|blog|URL] path/to/app -> creates a new app from the repository at URL at the path supplied
  fragmenta -> builds and runs a fragmenta app
  fragmenta server -> builds and runs a fragmenta app
  fragmenta test  -> run tests
  fragmenta migrate -> runs new sql migrations in db/migrate
  fragmenta backup [development|production|test] -> backup the database to db/backup
  fragmenta restore [development|production|test] -> backup the database from latest file in db/backup
  fragmenta deploy [development|production|test] -> build and deploy using bin/deploy
  fragmenta generate resource [name] [fieldname]:[fieldtype]* -> creates resource CRUD actions and views
  fragmenta generate migration [name] -> creates a new named sql migration in db/migrate
------

ヘルプの様子だと、cmsを作成する以外に、アプリケーションのスケルトンやブログを作る事も出来そうです。

URLとあるのはレポジトリから新規プロジェクトを作る、という所でしょうか。
PHPのパッケージャ、Composerでも他の人の作ったプロジェクトテンプレートから新たにプロジェクトを作ったりする事が出来たので、そのような使い方を考えているのではないか?と思います。

まず、アプリを試してみる事にします。

# GOPATHをworkspace/に設定しているので、src以下で開発
$ cd src
# とりあえずローカルで試すだけなので、app_testとしておいた
$ fragmenta new app app_test
$ cd app_test
$ tree
├── bin
├── db
│   ├── backup
│   └── migrate
│       ├── 2017-05-27-072519-Create-Database.sql
│       └── 2017-05-27-072519-Create-Tables.sql
├── log
├── public
│   ├── assets
│   │   ├── images
│   │   │   └── app
│   │   │       └── logo.png
│   │   ├── scripts
│   │   │   └── app-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.min.js
│   │   └── styles
│           ├── app-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.min.css
│           └── normalize.min.css
├── secrets
│   ├── assets.json
│   └── fragmenta.json
├── server.go
├── server_test.go
└── src
    ├─ app
...

デフォルトだとsqlなどあるので、使わなくてもデータベースが必要なようです。

mysqlサーバのセットアップ

$ mysql-ctl install
MySQL 5.5 database added.  Please make note of these credentials:

Root User: username
Database Name: c9

インストールするとユーザ名とデフォルトで出来ているデータベース名が表示されます。
username の所は、初期で環境変数の C9_USER となるようです。

mysqlサーバの起動と確認

$ mysql-ctl start
$ mysql-ctl cli
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| c9                 |
| mysql              |
| performance_schema |
| phpmyadmin         |
+--------------------+
5 rows in set (0.01 sec)

設定などは、secrets/fragmenta.jsonにあるようです

$ cat secrets/fragmenta.json
{
        "development": {
                "assets_compiled": "no",
                "db": "c9",
                "db_adapter": "mysql",
                "db_pass": "",
                "db_user": "username",
                "hmac_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                "log": "log/development.log",
                "path": "app_test",
                "port": "8080",
                "secret_key": "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
        },
...

hostの指定が無いのですが、軽くソースを見て見た限りだと、設定できそうです。
https://github.com/fragmenta/query/blob/master/adapters/database_mysql.go#L20
port番号は、前回見た通りに、8080に設定しておくと良いです。

$ cat secrets/assets.json
{
        "app": {
                "scripts": "d0d2a631d0b5b2e52b6def992031e9fd1309a66d",
                "styles": "58a0afbf47fbb0647dc34dff83732be2509c4c7e",
                "files": {
                        "src/app/assets/styles/admin.css": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "src/app/assets/scripts/adom.js": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "src/app/assets/styles/app.css": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "src/app/assets/scripts/app.js": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "src/lib/editable/assets/styles/editable.css": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "src/lib/editable/assets/scripts/editable.js": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "src/users/assets/styles/users.css": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        "src/users/assets/scripts/users.js": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
                }
        }
}

同じディレクトリにあるには、CSSなどのファイルが指定してります。
内容を圧縮して配置する設定のようです。

$ ls db/migrate
2017-05-27-072519-Create-Database.sql* 2017-05-27-072519-Create-Tables.sql*
$ cat 2017-05-27-072519-Create-Database.sql
/* Setup database for app_test */
CREATE USER "app_test_server" WITH PASSWORD 'xxxxxxxxxxx';
CREATE DATABASE "app_test_development" WITH OWNER "app_test_server";

fragmenta migrateでミグレートするようですが、ユーザやデータベースを作成するようなので、Create-Tables.sqlの内容をデータベースに流しておきます。
fragmenta testでテストができるようですが、データベース作成のテストなどもある為、今回は飛ばします。

$ fragmenta server
06:39:07 
------
Fragmenta version: 1.5rc
------
06:39:07 Building server...
06:39:07 Running go fmt at ./...
06:39:09 Building server at /home/ubuntu/workspace/src/app_test/bin/fragmenta-server-local
06:39:10 Build completed successfully in 1.368860262s
06:39:10 Launching server...
2017/06/04 06:39:10 #info Opened log file at log/development.log
2017/06/04 06:39:10 #info Finished loading assets in 96.379µs
2017/06/04 06:39:10 #info Finished loading templates in 3.761767ms
2017/06/04 06:39:10 #info Finished opening in 1.398579ms database c9 for user username
2017/06/04 06:39:10 #info Starting server in Development mode on port 8080

これで、
https://{projectname}-{username}.c9users.io
にアクセスするとトップページが表示されるようになります。

ルーターの設定

$ cat src/app/routes.go
package app

import (
        "github.com/fragmenta/router"

        "app_test/src/users/actions"
)

// SetupRoutes adds routes for this app to this router.
func SetupRoutes(r *router.Router) {

        // Resource Routes
        r.Add("/users", useractions.HandleIndex)
        r.Add("/users/create", useractions.HandleCreateShow)
        r.Add("/users/create", useractions.HandleCreate).Post()
        r.Add("/users/{id:[0-9]+}/update", useractions.HandleUpdateShow)
        r.Add("/users/{id:[0-9]+}/update", useractions.HandleUpdate).Post()
        r.Add("/users/{id:[0-9]+}/destroy", useractions.HandleDestroy).Post()
        r.Add("/users/{id:[0-9]+}", useractions.HandleShow)
        r.Add("/users/login", useractions.HandleLoginShow)
        r.Add("/users/login", useractions.HandleLogin).Post()
        r.Add("/users/logout", useractions.HandleLogout).Post()
        r.Add("/users/password", useractions.HandlePasswordReset)
        r.Add("/users/password/reset", useractions.HandlePasswordResetShow)
        r.Add("/users/password/reset", useractions.HandlePasswordResetSend).Post()
        r.Add("/users/password/sent", useractions.HandlePasswordResetSentShow)

        // Set the default file handler
        r.FileHandler = fileHandler
        r.ErrorHandler = errHandler

        // Add a files route to handle static images under files
        // - nginx deals with this in production - perhaps only do this in dev?
        r.Add("/files/{path:.*}", fileHandler)
        r.Add("/favicon.ico", fileHandler)

        // Add the home page route
        r.Add("/", homeHandler)

}

上の最後から、トップページはhomeHandlerが担っているという事がわかるので、見てみます。

$ cat src/app/home.go
package app

import (
        "github.com/fragmenta/router"
        "github.com/fragmenta/view"
)

// HandleShowHome serves our home page with a simple template.
// This function might be moved over to src/pages if you have a pages resource.
func homeHandler(context router.Context) error {
        view := view.New(context)
        view.AddKey("title", "Fragmenta app")
        view.Template("app/views/home.html.got")
        return view.Render()
}

テンプレートにapp/views/home.html.gotを使用しているようです。

$ cat src/app/views/home.html.got
<section class="padded">
<h1>{{.title}}</h1>
<p>A bare-bones app template</p>
</section>

ここのA bare-bones app templateを書き換えると、トップページが書き換わります。

感想

ここでは書いていませんが、ドキュメントの通りに進めてみても動作しなかったり、Windowsで試してみると生成されるパスが正しく無い為に動作しなかったりと不備が目立ちます。
コミュニティにもまだ活気が無い感じですが、Goのオープンソース製CMSは今の所、他に無さそうなので、何かのきっかけでブレイクするのではないでしょうか?
(と言いつつ、今回はCMSまで動かせていませんが、また別の機会に試してみる事にします。)