まっしろけっけ

めもてきなやーつ

表参道.rb #5 にてLTしてきた

表参道.rb is

omotesandorb.connpass.com

おしゃれな感じのする地域Rubyコミュニティ
人気らしく毎回すぐに枠が埋まっているらしい、
今回は会場が会社から徒歩で行けたことと先月の途中から勤務時間が変更になって
勉強会に参加しやすくなった(会社的には勉強会行くって言えば早く退社したり実は出来るのだが)ので
行くならLTしよ〜という軽いノリでLT枠で参加した。

今回は第五回目だが自分は初参加でした。

LT

発表者が十数名いて色々なテーマでLTされていたので面白かった。
英語力…ということ出来事がちょうどあった日に英語に関するgemの話を聞けたり
jsの話があったり,.rbなのにErlang + Elixirの話しかしなかったりw
もちろんRubyの話もあったし、frozen literalとかはこれはhsbtさんが言ってたあれか!という感じだった。

自分の発表内容

自分はStyleStatsの宣伝紹介をしてきました。
資料は下記

www.slideshare.net

  • StyleStatsの説明
  • Ruby StyleStatsの説明
  • Ruby StyleStatsで使用したgemの説明
  • v0.2.0の説明
  • v1.0.0への展望

という感じでLTを行いました。

実はLTした際は一部のtestが不十分だったので、まだv0.2.0を公開できていなかった。
なのでその旨を説明したページが1,2ページあった。

懇親会など

sansan株式会社さんが手の込んだお食事を大量に提供してくれていて
結構お腹いっぱいになってしまった。感謝感謝です。

色々な方とお話し出来て面白かった。
この業界の狭さをまたまた感じることとなったのでした。

最後に

表参道.rb 運営者の方々
sansan株式会社様
お話しをさせて頂いた方々
LTを聞いて頂いた方々
ありがとうございました!!1

Rails Girls Tokyo 5thでコーチとスポンサーLTしてきたよっていう話

Rails Girls is 何

railsgirls.com

ここら辺に書いてあります。
何故やってるかは下記あたりが参考になるかと

Rails Girls: Not Only for Girls - RubyKaigi 2014
日本RailsGirls活動紹介 // Speaker Deck


Girlsという名前が付いてますが、女性同伴なら男性もおkらしいですよ。
今回1名いましたね。(スタップT着てない男性いるな…?とは思っていたのですが自分の周りのことでいっぱいいっぱいで後で参加者だと知った)

何故コーチをやったのか?

いくつか理由があります。
ここに書いた以外にも細かい理由ならもっとあると思う。(単純に面白そうとか)

誰かに教えるといこと

誰かに何かを教えるということで、間違っていることを教えないようにとか
教えようとしている内容をもう一度自分で勉強してみたり
自分にとっても色々と学びがあるというのは経験上知っていたので自分が成長する為にという点
前職の際に Ruby を教えた経験が一度あるがなんか上手く教えることが出来なかったな…というモヤモヤもあった。

4th の開催の際の出来事

Rails Girls を知ったのは約1年前の 4th 開催の時で、
その際もコーチに応募しようと思っていたのですが忘れていて結局応募しなかった。
当時同じチームで働いていたフロントのエンジニアの女性が 4th に参加してすごく楽しかったと言っていたし、
その後の業務で Rails 側の簡単な修正とかもやってくれるようになって
Rails Girls の恩恵を少なからず受けていたのでそういう風な人が増えればいいなと思っていた。
また、その女性は社内の研修っぽい案件で web server が必要になり Rails 使って作っていて
そのレビューとか頼まれてしていた。

4th 開催時の自分の周りの環境

周りに Rails のプロジェクトが少なかったこともあり、
普及したいと思っていた自分にとって何かしらヒントが得られればと当時は思っていた。
今は単純に Rails 使う人増えればいいなと思っている。

多様性の話

上記で紹介したスライドでも言及されていますが、
女性だから◯◯じゃないといけない、男性だから◯◯じゃないといけないとか
そういうのは正直アホくさって思ってる人間なので女性のエンジニアが増えるのは良いことだと思った。
女性エンジニアが増えることにより、色々な考えが生まれ、それがサービス等に反映されていくことだと思っている。

Rails Girls Tokyo 5th

1日目は install day ということで RubyRails を install して終わり
2日目で ワークショップとして Rails でアプリケーションを作成する。

だいたい5,6人のチームに分かれそれぞれのチームにコーチが3人ずつ着くといった感じだった。
自分のチームは@yotii23,@kunitooと自分がコーチ
事前の打ち合わせでチームの進行や説明役を自分がやることになっていた。
(鳥居さんは去年のRubyKaigiの発表聞いていたしschooの配信も見てたり一方的に知っていたので一緒のチームで進行的なやつをやるのはプレッシャーだったw)

当日の様子を知りたい方は Twitter でタグでも漁れば出てくるとおもいます。

感想

Rails Girls がどうやって作られているかの一端でも知ることが出来た。
・実際に教えてみると、想定していなかった質問(sqlite3のデータみたいとか)が飛んできてその場で調べたりした。
・プログラミングが初めてという方に説明することの難しさ、
自分が頭で理解していることを言語化し他人に説明する難しさをとてもを感じた。
・チーム内の進行や説明をする役を自分からやるって言って結果的には良かった。緊張もしたが上記のような説明の難しさを感じることが出来たし、鳥居さんからアドバイス貰ったり、手助けをして貰ったり人に教える際の勉強になった。
・なにより Girls に楽しかったと言ってもらえたし喜んで貰えたのが嬉しかった。
・楽しかった。
・かわいいTシャツ貰った。

・この業界は狭いなと感じることが多々あった

言いたいことがもっとある気がするけど、とりあえず終わりです。
オーガナイザーの方々、コーチ、スタッフの方々、参加者の皆さん貴重な体験をありがとうございました。

スポンサーLT

スポンサーLT やることになった経緯

@hsbtこと弊社の柴田さんが slack にて「当日RubyConf Taiwan 行ってるから誰か代わりにLTやってきて」と発言

その時はまだコーチをやることが決まってなかったのでとりあえずコーチやることになったら考えよ程度
その週末くらいにコーチをやることが決まったので

@shiro16「@hsbt: まだ Rails Girls の LT って決まりましたか?」
@hsbt「まだです」
@shiro16 「じゃやります」

みたいな感じのやりとりがあり入社2ヶ月の新人がスポンサーLTすることに決まった。

LT 資料

画像がほとんどなので意味わからないかもしれないけどとりあえず置いておきます。
会社の説明、サービス紹介、CTO,チーフエンジニア紹介、面白制度や新卒研修等を紹介した。(一部削ってます)

www.slideshare.net

最後に

弊社ではエンジニアをはじめ、いろんな人を募集していますので下記から何卒pepabo.com

RubyでStyleStatsをつくった

StyleStats is 何?

StyleStatsの説明は下記をご覧いただくのが一番早いかと思います。

html5experts.jp

簡単に言うと@t32kさんが作ったCSSを解析するツールです。
先週のYAPC::Asia Tokyo 2015の2日目でLTをなさっていたっぽいので
知っている方もいるかと思います。

経緯

今回StyleStatsをRubyで作ることになった経緯は下記です。

こんなことをつぶやいていたので、おっ!と思って反応してみた

そしたらお願いされたので30秒くらい考えて面白そうだと思ったので
頑張ってみる旨を伝えた。
8月中に公開できればいいかなという感じで考えていた。

t32kさんとは前職で一時期一緒のチームで働いていたり等の関わりがありました。

作る際に注意した点

  • CLIツールなので出来るだけ他のGemに依存しないようにしたい。
  • できる限り本家のStyleStatsと同じオプション等を指定して使えるようにしたい。

特に注意した点は上記の2つ

gem依存問題に関して

今回実装する際の大きなポイントが

  • CSSを解析する必要があるのでCSSをパースする
  • URLを渡された際にはHTMLをパースしてSTYLEタグとLINKタグからstylesheetを取得する

上記の2点がありそれを行うgemを使うか自前で実装するかする必要があった。
自前で実装するにしては結構な時間が必要になるなと思ったのでgemを使うことに決めた。

CSSのパースに関しては premailer/css_parser · GitHub こちらのgemくらいしか
要件を満たしてくれそうなやつがなかったので選択。

HTMLのパースに関してはNokogiriが有名ですがNokogiriはインストールする際に
libxmlのエラーが発生するというよく見かける問題があるので、
そこで諦められるのは嫌だったので他のgemを探したら YorickPeterse/oga · GitHub こちらのgemが良さそうだったので選択した。
(最初はNokogiriを使っていた)

作ってみての感想

出来たのがこちら
最初はgem名もstylestatsで作っていたが、本家とこのgemを入れた際に面倒くさいなと思って
Rubyっぽくstyle_statsにした。

optionのほとんどが未実装の状態だがt32kさんに確認してもらったら
どんどんリリースしちゃっていいよって感じだったのでリリースすることにした。

github.com

  • 作ってみて気づいたがStyleStatsは思っていた以上に高機能で良くできていた。
  • Rubyだったので文字の色は赤くしてみた。
  • まだoptionはformatしか指定出来ない。
  • optionは今後のversion upで対応していく。
  • CSSにそんなに詳しくなかったが、CSSのParserを自作出来るのでは?と思える程度には理解出来た。気がする
  • 作ったけど、クソコードな部分が多いので、v1.0.0までに全部書きかわる可能性があるかもしれない
  • 楽しかった!

最後に

このような機会を与えて頂き有り難く思います。
実は勉強会かtwitterでStyleStatsを知った時に下記のような感想を持っていました。
なのでとても楽しく開発できたし、少しても関われることができありがたいという思いです。

golangのフレームワークrevelを使用して掲示板っぽいものを作ってみる

はじめに

今回は golang の revel framework を使用して掲示板っぽいやつを作ってみる。
掲示板っぽいと言っても基本的には APIJson を返すことにする。
しかし html を返す場合もやることはほぼ変わらない。

今回作成する API は一般的な掲示板でいうスレッドは存在せず
レスのみを扱う。(今後スレッド対応やログイン対応等を行っていくかもしれない)
endpoint は下記のようにする

http method path 説明
GET /comments 一覧
GET /comments/:id 詳細
POST /comments 登録
DELETE /comments/:id 削除

revel is 何 ?

revel は高機能な重量級の framework で Ruby で言うと sinatra というより
Rails に近い framework になります。

環境

$ go version
go version go1.4.2
$ mysql --version
mysql  Ver 14.14 Distrib 5.6.13

revel を install する

下記で install できる

$ go get github.com/revel/revel # revel framework を取得
$ go get github.com/revel/cmd/revel # revel command を取得

プロジェクトを作成してみる

とりあえずハロワが表示されるとこまで進める。

$ revel new github.com/shiro16/golang-bbs # rails new みたいなやつ
~
~ revel! http://revel.github.io
~
Your application is ready:
   ${GOPATH}/src/github.com/shiro16/golang-bbs

You can run it with:
   revel run github.com/shiro16/golang-bbs
$ cd ${GOPATH}/src/github.com/shiro16/golang-bbs
$ revel run # applicaton の起動

これで「http://localhost:9000/」にアクセスすると
「It works!」が表示される。

API の endpoint を定義する

routing を追加する

routing は「config/routes」で管理されている
下記のように編集する。
今回の Api の path は「/api/v1」をベースにする

GET     /                                       App.Index
+ GET     /api/v1/comments                        ApiV1Comments.Index
+ GET     /api/v1/comments/:id                    ApiV1Comments.Show
+ POST    /api/v1/comments                        ApiV1Comments.Create
+ DELETE  /api/v1/comments/:id                    ApiV1Comments.Delete
controller を作成する

今回は api で共通して使うであろう Error 処理等をまとめて記述する
ベースとなる controller も作成しておく

// app/controllers/api/v1/v1.go
package controllers

import (
        "github.com/revel/revel"
        "github.com/shiro16/golang-bbs/app/utils"
        "net/http"
)

// 埋め込みによって revel.Controller をラップした ApiV1Controller を定義する
type ApiV1Controller struct {
        *revel.Controller
}

// エラーの際に返す Json 用の構造体
type ErrorResponse struct {
        Code    int    `json:"code"`
        Message string `json:"message"`
}

// 正常な際に返す Json 用の構造体(今回は1種類で統一する)
type Response struct {
        Results interface{} `json:"results"`
}

// 引数として渡されて interface にリクエストの Json の値を格納する
func (c *ApiV1Controller) BindParams(s interface{}) error {
        return utils.JsonDecode(c.Request.Body, s)
}

// Bad Request Error を返すやつ
func (c *ApiV1Controller) HandleBadRequestError(s string) revel.Result {
        c.Response.Status = http.StatusBadRequest
        r := ErrorResponse{c.Response.Status, s}
        return c.RenderJson(r)
}

// Not Found Error を返すやつ
func (c *ApiV1Controller) HandleNotFoundError(s string) revel.Result {
        c.Response.Status = http.StatusNotFound
        r := ErrorResponse{c.Response.Status, s}
        return c.RenderJson(r)
}

// Internal Server Error を返すやつ
func (c *ApiV1Controller) HandleInternalServerError(s string) revel.Result {
        c.Response.Status = http.StatusInternalServerError
        r := ErrorResponse{c.Response.Status, s}
        return c.RenderJson(r)
}

これでベースとなる処理が完了したので comments controller を作成していく

// app/controllers/api/v1/comments.go
package controllers

import (
        "github.com/revel/revel"
        "github.com/shiro16/golang-bbs/app/controllers"
)

type ApiV1Comments struct {
        ApiV1Controller
}

func (c ApiV1Comments) Index() revel.Result {
        r := Response{"index"}
        return c.RenderJson(r)
}

func (c ApiV1Comments) Show(id int) revel.Result {
        r := Response{"show"}
        return c.RenderJson(r)
}

func (c ApiV1Comments) Create() revel.Result {
        r := Response{"create"}
        return c.RenderJson(r)
}

func (c ApiV1Comments) Delete(id int) revel.Result {
        r := Response{"delete"}
        return c.RenderJson(r)
}

これで controller の作成は完了。
DB へ接続してデータを取得する等は次で行います。
実際に起動してみると下記のようになるかと。

$ revel run github.com/shiro16/golang-bbs

# 別窓等で
$ curl http://localhost:9000/api/v1/comments
{
  "results": "index"
}
$ curl http://localhost:9000/api/v1/comments/1
{
  "results": "show"
}
$ curl -X POST http://localhost:9000/api/v1/comments
{
  "results": "create"
}
$ curl -X DELETE http://localhost:9000/api/v1/comments/1
{
  "results": "delete"
}

DB 周りの処理を作成する

現状 ORM が revel には無い為自分で好きなものを使う。
revel の samples では gorp が使われているが
今回は gorm を使用する。

validation には validator を使用する。

DB の接続情報を追加

golang_bbs_development」という名前の DB 名にしています。

// conf/app.conf
[dev]
mode.dev = true
results.pretty = true
watch = true
watcher.mode = "normal"
log.trace.output = off
log.info.output  = stderr
log.warn.output  = stderr
log.error.output = stderr
db.info = "root@/golang_bbs_development?charset=utf8&parseTime=True
model を作成する

gorm を使用するので取得する
validator も取得しておく

$ go get github.com/jinzhu/gorm
$ go get gopkg.in/validator.v2

comment model を作成

// app/models/comment.go 
package models

import (
        "time"
)

type Comment struct {
        ID        uint64     `gorm:"primary_key" json:"id"`
        Nickname  string     `sql:"size:64" json:"nickname" validate:"max=64"`
        Body      string     `sql:"size:255" json:"body" validate:"min=1,max=255"`
        CreatedAt time.Time  `json:"created_at"`
        UpdatedAt time.Time  `json:"updated_at"`
        DeletedAt *time.Time `json:"deleted_at"`
}

DB への接続などの初期化処理を作成

// app/controllers/gorm.go
package controllers

import (
        _ "github.com/go-sql-driver/mysql"
        "github.com/jinzhu/gorm"
        "github.com/revel/revel"
        "github.com/shiro16/golang-bbs/app/models"
        "log"
)

var DB *gorm.DB

func InitDB() {
        db, err := gorm.Open("mysql", dbInfoString())
        if err != nil {
                log.Panicf("Failed to connect to database: %v\n", err)
        }

        db.DB()
        db.AutoMigrate(&models.Comment{}) # ここで table の作成を行っている
        DB = &db
}

func dbInfoString() string {
        s, b := revel.Config.String("db.info")
        if !b {
                log.Panicf("database info not found")
        }

        return s
}

上記を呼び出す処理を追記

// app/init.go
- import "github.com/revel/revel"
+ import(
+         "github.com/revel/revel"
+         "github.com/shiro16/golang-bbs/app/controllers"
+ )

func init() {
....
+ revel.OnAppStart(controllers.InitDB) // 28行目くらいに
}

DB 周りの処理の作成が完了し、
残すは作成した model を controller で実際に使用する処理を残すのみ

controller で model を使用する

comments controller を編集していく

package controllers

import (
	"github.com/revel/revel"
+ 	"github.com/shiro16/golang-bbs/app/controllers"
+ 	"github.com/shiro16/golang-bbs/app/models"
+ 	"gopkg.in/validator.v2"
)

type ApiV1Comments struct {
	ApiV1Controller
}

func (c ApiV1Comments) Index() revel.Result {
+ 	comments := []models.Comment{}

+ 	if err := controllers.DB.Order("id desc").Find(&comments).Error; err != nil {
+ 		return c.HandleInternalServerError("Record Find Failure")
+ 	}

+ 	r := Response{comments}
- 	r := Response{"index"}
	return c.RenderJson(r)
}

func (c ApiV1Comments) Show(id int) revel.Result {
+ 	comment := &models.Comment{}

+ 	if err := controllers.DB.First(&comment, id).Error; err != nil {
+ 		return c.HandleNotFoundError(err.Error())
+ 	}

+ 	r := Response{comment}
- 	r := Response{"show"}
	return c.RenderJson(r)
}

func (c ApiV1Comments) Create() revel.Result {
+ 	comment := &models.Comment{}

+ 	if err := c.BindParams(comment); err != nil {
+ 		return c.HandleBadRequestError(err.Error())
+ 	}

+ 	if err := validator.Validate(comment); err != nil {
+ 		return c.HandleBadRequestError(err.Error())
+ 	}

+ 	if err := controllers.DB.Create(comment).Error; err != nil {
+ 		return c.HandleInternalServerError("Record Create Failure")
+ 	}

+ 	r := Response{comment}
- 	r := Response{"create"}
	return c.RenderJson(r)
}

func (c ApiV1Comments) Delete(id int) revel.Result {
+ 	comment := models.Comment{}

+ 	if err := controllers.DB.First(&comment, id).Error; err != nil {
+ 		return c.HandleNotFoundError(err.Error())
+ 	}

+ 	if err := controllers.DB.Delete(&comment).Error; err != nil {
+ 		return c.HandleInternalServerError("Record Delete Failure")
+ 	}

+ 	r := Response{"success"}
- 	r := Response{"delete"}
	return c.RenderJson(r)
}

これで各 endpoint にアクセスしてみる

$ revel run github.com/shiro16/golang-bbs
# 別窓等で
$ curl -H "Content-type: application/json" -X POST -d '{"nickname":"shiro16", "body":"test comment"}' http://localhost:9000/api/v1/comments
{
  "results": {
    "id": 1,
    "nickname": "shiro16",
    "body": "test comment",
    "created_at": "2015-08-13T21:20:46.681910871+09:00",
    "updated_at": "2015-08-13T21:20:46.681910871+09:00",
    "deleted_at": null
  }
}
# validation がちゃんと機能しているかチェック
$ curl -H "Content-type: application/json" -X POST -d '{"nickname":"shiro16", "body":""}' http://localhost:9000/api/v1/comments
{
  "code": 400,
  "message": "Body: less than min"
}
$ curl http://localhost:9000/api/v1/comments
{
  "results": [
    {
      "id": 1,
      "nickname": "shiro16",
      "body": "test comment",
      "created_at": "2015-08-13T12:20:47Z",
      "updated_at": "2015-08-13T12:20:47Z",
      "deleted_at": null
    }
  ]
}
$ curl http://localhost:9000/api/v1/comments/1
{
  "results": {
    "id": 1,
    "nickname": "shiro16",
    "body": "test comment",
    "created_at": "2015-08-13T12:20:47Z",
    "updated_at": "2015-08-13T12:20:47Z",
    "deleted_at": null
  }
}
$ curl http://localhost:9000/api/v1/comments/2 
{
  "code": 404,
  "message": "record not found"
}
$ curl -X DELETE http://localhost:9000/api/v1/comments/1
{
  "results": "success"
}

まとめ

こんな感じで雑な部分もありますが revel を使って基本的な処理の作成が完了しました。
validation に関しては model にてチェックを行った方がいいかと思いますが、
今回は時間の関係で controller にて行っています。
今回作成したものはこちらで公開しています。
API 以外の処理も追加していますので参考にしてください。

今回の説明以外の詳しい内容は下記を参考にするといいと思います。
とくに sample を配布しているので「go get github.com/revel/samples」で取得して
見てみるといいかと思います。
Welcome to Revel, the Web Framework for Go!

GMOペパボに入社しました

はじめに

タイトルの通りGMOペパボに入社しました。
7月1日から働き始めてるので実際には約10日程たってます。
なんで転職したかとか周りの人にあまり説明+お知らせをしていないので
それ用の記事と現在の自分の考えをメモっておくように記事を書いてます。

転職しようと思った訳

前職もweb系のエンジニアとしてRuby書いていたわけですが、
今年(2015年)の初め頃から、
社内でRubyRailsを使用したサービス開発で学びや技術的な刺激を受ける機会が激減したと感じ始めた。
激減した理由としては当時1年半くらいRuby書いていて、
社内でRubyをメインで使用して開発しているエンジニアとしては経験年数が長くなり知識が増えたことが
原因だと思っている。

その為、技術的な刺激を求め社外のRuby系の勉強会などに参加したりしていたが
普段自分が何気なく書いているコードに関しても、もっと良い方法があるんじゃないか?
とか色々考えるようになり、転職をしようかと考えた。

ただ、すぐに転職活動を行わなかったのはまだ当時の会社でやりたいことがあったこと
担当していたサービスを任せられるエンジニアを育成すること
その他色々な理由で2015年後半に転職活動をしようと思っていたのです。

2015年後半…?

「え、おまえ後半入って速攻で転職してるやん」ってなると思うのですが
理由は色々あるのです。
タイミング的なあれだったり、ゴールデンウィークからの社会復帰に失敗したからとか
大人の事情とか、そういうものだと思ってください。
悪いことはしてません

なんでペパボ?

転職する一番の理由がRubyの凄いエンジニアのいる会社で働いて自分の技術力をもっと磨きたいなので
とりあえず頭に浮かんだ会社が2社ありその片方がペパボでした。

pepabo.com

とりあえず話聞きたいと思い上記の制度を利用しお話を聞きに行くことに
@kentaro,@hsbtのお二人を指名させていただきました。
現状抱えている課題や今後人が増えていく上で起こりえるであろう課題等、本当に細かいことまでお答えしていただき
当時はそれなりに人数の多い会社で働いていたのでRubyでの開発以外のそういう部分の課題の解決にも携われたら面白いだろうなと思い受けてみたら、ありがたいことに採用して頂いたという経緯です。
頭に浮かんだもう一社についてはお祈…

実際どうなの?

1,2週間働いただけなのでまだまだわからないこと多めですが、
3日目くらいからSlackで@udzuraさんと技術的な会話が出来たり、
技術的な刺激を受ける機会は多いなと感じている。
やらなければいけないことや技術的な課題も多々あるのでやり甲斐も凄く感じていて
楽しくなりそうな気配はしている。

さいごに

こんな経緯で今回GMOペパボで働くことになりました。
今後に関して当分はRubyでサービスの開発を行っていくとのがメインになるかと思いますが、
解決したい課題も多々あるので、
インフラや基盤の方でサービスを作るエンジニアを支えるという立場を経験するのも面白そうだなという思いがあります。

ペパボに興味がある方はペパランチョンで話を聞きに来るも良し下記から申し込むのも良しかと思います。

pepabo.com


このエントリーはもし誰かに怒られたら消します

PHPでmemcachedに保存されたセッション情報をRubyで扱う

経緯

PHPで作成されたシステムで発行されたsession idを元に
Rubyからそのセッションに格納されている情報を知りたいかもしれないという状況が
あるかもしれない。
無事社会復帰を果たした会社で話題になったので調べてみた。
前々職の際にPHPmemcachedに関して結構調査してたりしたので大分行けそうな気はしていた。
途中経過をメモ

環境

php.iniにて下記のように設定

session.save_handler = memcached
session.save_path = "localhost:11211"

memcachedlocalhostのport11211で動かしています。

PHPにてsessionに何かを保存する

今回は適当なデータを格納するスクリプトを作成
session.phpというファイル名で保存

#!/usr/bin/php
<?php
session_start();

echo $_SESSION['count'] = rand(1, 100);
$_SESSION['testkey'] = 'hoge';

echo session_id();
echo "\n"
?>

実行してsession idを確認してみる

$ php session.php
66
f1sk3iprn07l2vu6a5e09dqd86 # これがデータを格納したsession id

memcachedにどのようなデータが格納されているか確認する

memcached-toolっていうコマンドを使ってmemcachedをいじれたりする

$ memcached-tool localhost:11211 dump
Dumping memcache contents
  Number of buckets: 1
  Number of items  : 1
Dumping bucket 3 - 1 total items
add memc.sess.key.f1sk3iprn07l2vu6a5e09dqd86 0 1435838226 30
count|i:66;testkey|s:4:"hoge";

先ほどのphpスクリプトを実行して表示されたsession idの前に
「memc.sess.key.」が付いている。
ここをみるとPHPが勝手に付ける仕様のようだ。

セッションに格納していたデータは「count|i:66;testkey|s:4:"hoge";」このようにシリアライズ
されて保存されている。
phpの標準のserialize関数ではなくmemcachedの独自のシリアライズっぽい?

Rubyで取得してみる

memcachedのデータを扱うgemはそのままevan/memcached · GitHubを使ってみたのですが、ここでエラーが出たので断念。
phpで独自のシリアライズ保存されたデータだからそりゃそうなのだが…

ということでmperham/dalli · GitHubこちらを試してみた。

$ gem install dalli
$ irb
irb(main)> require 'dalli'
irb(main)> dalli_client = Dalli::Client.new('localhost:11211')
irb(main)> dalli_client.get "memc.sess.key.f1sk3iprn07l2vu6a5e09dqd86"
=> "count|i:66;testkey|s:4:\"hoge\";"

これでシリアライズされたデータが取得出来た。

まとめ

PHPで生成されたsession idを元にsessionに格納されたデータ(シリアライズされたデータ)を
取得することに成功した。

とりあえず今日はここまで
TODOは以下

しかし久しぶりにPHP書いたな

技術書をまとめ買いしたよ

ネタがあまりないので雑談
なぜか2週間くらい暇になり、
なぜか会社でRubyを教えたm君にAmazonギフト券を貰ったので
3冊ほどまとめ買いしたものと最近読んだ1冊をまとめておく。
本当はkindleのセールの際に買おうと思ったのだがセールが終わってしまい買えなかったので
このタイミングで買った

買った本

自分はインフラエンジニアではないが、いろいろやったりしているので
一般的なインフラエンジニアと認識の違いがないかを知りたかったので基本的な本を選んでみた。
大きな認識の違いがなかったが、細かい部分を知れたことと幾つかのコマンドやオプションを新しく知れたのでよかった。

インフラ/ネットワークエンジニアのためのネットワーク技術&設計入門

インフラ/ネットワークエンジニアのためのネットワーク技術&設計入門

ネットワーク関連があまり得意ではないので
勉強したくて読んでいる(もう少しで読み終わる)
図解が多くイメージがしやすい。

Amazon Web Services パターン別構築・運用ガイド

Amazon Web Services パターン別構築・運用ガイド

AWSを知らないで許されるのは小学生までだよねー」と最近思っている(危機感を感じている)ので
買った上記のネットワーク本が終わったら読む予定

クラウドつながりでOpenStackも面白そうなので買った。

まとめ

インフラの本ばかりになってしまいましたが、
インフラエンジニアに転向する訳ではありません。
(いずれそっち方向に進むのは結構ありだと思っているけど)
Serverspec本を書い忘れていたので、
上記の本を読み終わったらServerspec本を購入する予定