the industrial

ブログと言うより自分のためのメモ以外の何モノでもないです。でも読んでくださってありがとうございます。

スクール オブ ロック

スクール・オブ・ロック (字幕版)

 

前から見たかった映画。

そんな映画もプライムビデオなら無料で観れちゃうのスゴイ。

お金も人気もないギタリストが、嘘をついて小学校の先生に。

子どもたちの才能を見抜き、学校に内緒でロックバンドを組んでしまうお話。

ラストは気持ちよく終わった。

その2 ファイル分割してみる - golang製Web Framework 「echo」事始め

続き

前回の予告どおり、echoのサンプルプロジェクトのcrudモジュールについて、ソースファイルの分割をしてみる。

なお、普段からgolangを書いている人にとってはつまらない内容かもしれない。

けれども、なかなかどうしてimport何かではまったりして楽しかった。

ディレクトリ構成

こんな感じにしてみた

$ tree
crud
├── handler
│   ├── create.go
│   ├── delete.go
│   ├── list.go
│   └── update.go
├── model
│   └── user.go
└── router.go

分割

server.go から router.go へ

server.gorouter だけをまとめて、 router.go とした。

router.go
package main

import (
    "github.com/labstack/echo"
    "github.com/labstack/echo/middleware"
    "./handler"
)

func main() {
    e := echo.New()

    // Middleware
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    // Routes
    e.GET("/users", handler.ListUser)
    e.GET("/users/:id", handler.GetUser)
    e.POST("/users", handler.CreateUser)
    e.PUT("/users/:id", handler.UpdateUser)
    e.DELETE("/users/:id", handler.DeleteUser)

    // Start server
    e.Logger.Fatal(e.Start(":1324"))
}

modelディレクト

modelディレクトリはその名の通り、モデルを格納している。

model/user.go
package model

type (
    User struct {
        ID   int    `json:"id"`
        Name string `json:"name"`
    }
)

var (
    Users = map[int]*User{}
    Seq   = 1
)

var ( Users = map[int]*User{} Seq = 1 ) は永続層で、本来DBに置き換わる領域。

handlerディレクト

handler という名前はサンプルから取った名前。ビジネスロジックを格納する領域としており、 Service とした方が良いかもしれない。

それぞれCRUDの役割を持つロジックを定義している。

$ tree
crud
├── handler
│   ├── create.go
│   ├── delete.go
│   ├── list.go
│   └── update.go

create.go

package handler

import (
    "net/http"
    "github.com/labstack/echo"
    "../model"
)

func CreateUser(c echo.Context) (err error) {
    u := &model.User{
        ID : model.Seq,
    }
    if err := c.Bind(u); err != nil {
        return err
    }
    model.Users[u.ID] = u
    model.Seq++
    return c.JSON(http.StatusCreated, u)
}

router.goe.POST("/users", handler.CreateUser) にて下記の様なPOST リクエストを受け取り、データを格納する。

curl -v POST -H "Content-Type: application/json" "http://localhost:1324/users" -d '{
  "id" : 1,
  "name" : "Anthony Kiedis"
}'

modelは ./model というようにimportする。

GOPATH配下の場合は絶対パスを指定するのがお作法らしいが、今回の場合はGOPATH配下に構築はしていないので、相対パスで書いてしまっている。

ハマったコト

ID : model.Seq, の末尾に , が必要な理由が分からなかった…(削除するとコンパイルエラー)

update.go

package handler

import (
    "net/http"
    "strconv"
    "github.com/labstack/echo"
     "../model"
)

func UpdateUser(c echo.Context) (err error) {
    u := new(model.User)
    if err := c.Bind(u); err != nil {
        return err
    }
    id, _ := strconv.Atoi(c.Param("id"))
    model.Users[id].Name = u.Name
    return c.JSON(http.StatusOK, model.Users[id])
}

router.goe.PUT("/users/:id", handler.UpdateUser) にて下記の様なPUT リクエストを受け取り、データを更新する。

curl -v -X PUT -H "Content-Type: application/json" "http://localhost:1324/users/1" -d '{
  "name" : "Anthony Kiedis at Red Hot Chili Peppers"
}'
ハマったコト

Golang/echoとは直接関係ないのだけど、Elasticsearchをcurlで触っていた時はコンテントタイプは不要だった。

しかし、今回 -H "Content-Type: application/json" をちゃんと指定しないと、正しくJSONパラメータとして渡せなかった。

まあコレが普通なのだけど、イマイチ・・・。

list.go

package handler

import (
    "net/http"
    "strconv"
    "github.com/labstack/echo"
     "../model"
)

func GetUser(c echo.Context) (err error) {
    id, _ := strconv.Atoi(c.Param("id"))
    return c.JSON(http.StatusOK, model.Users[id])
}

func ListUser(c echo.Context) (err error) {
    return c.JSON(http.StatusOK, model.Users)
}

router.goe.GET("/users", handler.ListUser)e.GET("/users/:id", handler.GetUser) にて、下記の様なGET リクエストを受け取り、データを取得する。

curl -i -v GET "http://localhost:1324/users"
curl -i -v GET "http://localhost:1324/users/1"

delete.go

package handler

 import (
     "log"
    "net/http"
    "strconv"
    "github.com/labstack/echo"
    "../model"
)

func DeleteUser(c echo.Context) (err error) {
    log.Println(model.Users)
    id, _ := strconv.Atoi(c.Param("id"))
    delete(model.Users, id)
    log.Println(model.Users)
    return c.NoContent(http.StatusNoContent)
}

router.goe.DELETE("/users/:id", handler.DeleteUser) にて、下記の様なDELETE リクエストを受け取り、データを削除する。

curl -i -v -X DELETE "http://localhost:1324/users/1"

おわり

まあこんな所でしょうか。

あとは

  • DBへの永続化
  • エラーハンドリング
  • デプロイ

当たりの優先順位でやっていきたい。

golang製Web Framework 「echo」事始め

はじめに

なんだか今日は早く目が覚めてしまったので、久しぶりの朝活。

golang

最近 golang が気になり過ぎているのと、Webアプリ作るフレームワークも出てきている様なので、JavaScalaときて、第三の言語として扱えたらいいなーなんて思い、今年は真面目に勉強してみようかと。

実は前から既にちょくちょく書いていたのだけど、ちゃんとメモなりなんなりに残すのが大事なんだよね。

golang で書けるフレームワーク

フレームワークは僕が調べた中では、 martini というものが一番人気らしいのだけど、みんなが使っているものを勉強してもなーという天邪鬼な所があるので(Scalaの勉強を始めた時、周りの誰も使っていなかった)、 各フレームワークのベンチマーク を参考に、 echo というフレームワークを試すことにした。

なお、フレームワーク選びについては、下記Qiitaの記事を参考にさせていただいた。僕のブログ、というかこのエントリー含めてただのメモに比べると、こういう有益な記事には頭が上がらないっすね。

概観からGoのWebFrameworkを選ぶ

golang のインストール

いつも通りにbrew

$ brew install go

$GOPATH の設定

GOPATHが無いと色々不便(というか動かない?)みたい。

bashrcのPATHに、下記の様な感じで追加する。

export GOPATH=$HOME/.go
export PATH=$PATH:$GOPATH
$ go version
go version go1.7.5 darwin/amd64

echo の入手

go get コマンドで入手

go get -u github.com/labstack/echo

入手すると、 $GOPATHディレクトリに格納される(ココらへんは go get コマンドの話か)。

Helloworld

メモとか言っておきながら、やっぱり参考にする オフィシャルサイトのガイド そのまま。

HelloWorld

package main

import (
    "net/http"

    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })
    e.Logger.Fatal(e.Start(":1323"))
}

起動

$ go run helloworld.go
⇛ http server started on [::]:1323

localhost:1323 にアクセスすると、 Hello, World! と表示されるハズ。

echo のサンプルソース

下記に echo のサンプルソースが存在する。非常に参考になる。

~/.go/src/github.com/labstack/echo/cookbook
  • auto-tls
  • cors
  • crud
  • embed-resources
  • file-upload
  • google-app-engine
  • graceful-shutdown
  • hello-world
  • http2
  • jsonp
  • jwt
  • middleware
  • streaming-response
  • subdomains
  • twitter
  • websocket

見た感じ、crudやらfile uploadやらtwitter oath認証やらなんでも揃っているので、組み合わせるだけでアプリが作れそうな勢いw

次回は、このcrudを参考にし、MVCモデルの様にアプリを構築出来るようにするための第1歩として

  • router.go
  • listUser.go
  • createUser.go
  • updateUser.go
  • deleteUser.go

に分割してみる。

Supersetを試してみる

Supersetとは

Superset

宿泊施設マッチングサイトAirBnB(エアビーアンドビー)が提供する、データ可視化ツール

Supersetをインストールし、DBとつなぎ、Queryを書き、ヴィジュアライズしてダッシュボードを構築することで

マーケティングなどに役立てることが出来る

インストール方法

基本的にはオフィシャルサイトにある Superset’s documentation の通りにやっていけば良い

ここではMacOSにインストールする方法をメモっておく

Python の実行環境構築

SupersetはPython製なので、先ずはPython実行環境の構築

とは言っても、Homebrewで一発

$ brew install python

pkg-config、libffi、openssl をインストール

他に、pkg-configlibffiopenssl 等が必要となるそうなので、インストール

$ brew install pkg-config libffi openssl

pip について

pip | wikipedia

pip は、pythonのためのライブラリ管理ツール

homebrewやnodebrewみたいなもの

cryptography のインストール

cryptography

Python製の暗号化ライブラリ

env LDFLAGS="-L$(brew --prefix openssl)/lib" CFLAGS="-I$(brew --prefix openssl)/include" pip install cryptography

env については、 opensslcryptography を結びつける設定かな?

あまり詳しくなくて申し訳無し

virtualenv

Pythonの仮想環境を構築できるパッケージ。

こちらも、 Superset’s documentation を参考にインストール

pip install virtualenv

こちらの記事がとても詳しく書かれていたので、参考に

VIRTUALENV について | 今日のPython

superset のインストール

pip install superset

Adminユーザーを作成する

下記コマンドを実行すると、氏名、メルアド、パスワードを聞かれるので入力する

ここで入力した情報が初回ログインユーザーとなる

fabmanager は、 SupersetSQLiteにデータ登録するコマンド?

fabmanager create-admin --app superset

DBのイニシャライズを行う

これは、 Superset’s documentation に記載されたコトそのまま・・・

実際に何するかまでは調べていない

superset db upgrade

初期データを登録(多分スキップ可能)

これも、 Superset’s documentation に記載されたコトそのまま・・・

Supersetを利用する上で例となる、ものすごく豊富なデータを登録してくれる(スクリプトだと思っている)

superset load_examples

権限などの初期化

これも、 Superset’s documentation に記載されたコトそのまま・・・

superset init

サーバー起動

下記コマンドでSupersetを起動する

superset runserver

その後、 http://localhost:8088 にアクセスするとログイン画面が表示される

fabmanager で登録したユーザーでログインできる

MySQLに接続する

SQLAlchemyについて

SQLAlchemy

SQLAlchemyPythonのためのO/Rマッパーとのこと

Python界(とSuperset)のことは何もしらないので間違っていたら申し訳ないのだけど

SupersetはこのORMを採用している

MySql Connector (PyMySQLのインストール)

SQLAlchemyとは別に、MySQLにつなげるConnectorが必要になる

僕が試したのは PyMySQL 。これが良いものかどうかはワカラナイけど、とりあえずこれでつなぐことが出きた。

PyMySQLpip でインストールする。

pip install PyMySQL

MySql接続設定

上部の SourcesDatabases+ボタン から、 SQLAlchemy URI というフォームに

mysql+pymysql://{mysql_user}:{mysql_password}@localhost:3306/{database_name}

的なニュアンスでDB情報を入力

Test Connection で確認。

最後に

最後に、とか書いてるけど、とりあえずセットアップぐらいまでの手順しかまとめられなかった。

ただ、 superset load_examples をやってあげれば、それはもうエゲツないデータが登録され、グリグリしたなんかもう良くわからないグラフをダッシュボードから見ることが出来るので、是非お試しを。

エゲツないグラフは github のREADME.mdでgif確認出来るので、見てみると良い。

使い方はノリでできそう。

もう暫く触ってみたい。

シング・ストリート

シング・ストリート 未来へのうた(字幕版)

傑作!

 

最近、娘ちゃんが寝た後に嫁ちゃんと映画をよく観るのだけど、せっかくだから面白い映画を観たいモノ。そして、実際ヒットが続いて嬉しい。

 

アイルランドに住む冴えない男の子が、好きになった女の子の気をひく為にバンドを組むお話。

 

家庭環境とか、学校での厳しい規則、いじめから現実逃避する為に、バンドを組んだ仲間と曲を書き、それが力になって行く様は観ていて気持ち良い。

 

初めはもう笑っちゃうくらい見た目がダサいのだけど、どの曲もとてもとても良い曲。

 

物語が進むにつれて次第に様になって行き、ラストに至っては「初めから最後までずっとかっこよかったんじゃないかな?」と錯覚するほど、めちゃくちゃカッコイイんだ。

 

主人公の兄ちゃんが、とにかく弟に何でも教えてあげる、またこれがいい男。役者が気になって調べたら、まだ日本語のウィキペディアが無いみたい。Jack Reynor - Wikipedia

 

登場人物全員が良い味出してる、傑作映画!

 

究極のダサカッコイイ。

スタートレック イン トゥー ザ ダークネス

スター・トレック イントゥ・ダークネス (字幕版)

なんだかハマりだした笑

 

観る前は全く興味なかったのだけど、観てみるとこれが意外に面白い。エイブラムスさんマジックかな?

 

そんで、前作よりもこのイントゥーザダークネスの方が面白かった!

 

何よりベネディクト・カンバーバッチが良すぎ。

 

新作のビヨンドも早く観たいな(プライム化して欲しいな…w