読者です 読者をやめる 読者になる 読者になる

まっしろけっけ

めもてきなやーつ

WEB+DB PRESS Vol.92 「Web開発新人研修」の一部を書きました。

久しぶりのブログです。
4 月なのに 2016 年初ブログです。

本題

4 月 23 日発売の WEB+DB PRESS Vol.92 内の特集の一つである「Web開発新人研修」をペパボのエンジニアで寄稿させていただきました。
献本を頂いたのでざっくりと説明をしていこうと思います。
Web 開発とはどんなものなのかを浅く広く把握できる内容になっています。

自分は 3 章の「Web アプリケーションを作ろう」を担当しました。
Web アプリケーションの概要、フレームワークについて、Rails を使用して MVC を解説しながら、
ToDo アプリケーションを開発するという内容になっています。

コード自体は scaffold で作成されるファイルの中でも必要最低限なコードの作成と解説をしています。
scaffold は凄いのですが、凄過ぎてよくわからないけど動くという状況になることもあるかと思うので
このような形式で解説をさせて頂きました。


説明を行おうと思えば記事では触れていない部分もいくらでも説明出来るのですが、
今回は新人研修というのが目的の記事になるので、詳細な説明を省いている為説明不足な点も多いかと思います。
そのような点はイケメン先輩エンジニアが新人さんに教えてあげたり、逆に新人さんは先輩エンジニアにがんがん聞いていくのが良いのではないでしょうか

記事のまとめにも書いたのですが、Web アプリケーションを作るのは本当に楽しいので
今回の記事を読んでそのようなエンジニアが増えてくれたら嬉しく思います。

最後に、執筆の機会を下さった @june29 さん、執筆でお世話になりました株式会社技術評論社の池田さんありがとうございました。

gihyo.jp

STF を使ってブラウザ上から Android をいじってみた

STF is 何 ?

STF | Smartphone Test Farm

CyberAgent 社がオープンソースとして公開しているブラウザ上から Android を操作できるようになるやつ。
ブラウザ上から apk を install させたりもたしかできたはず
Android は様々な端末があり、
端末ごとに動作が違ったりで検証が大変 + 多数のプロダクトで Android アプリを開発していると端末の貸し借りが発生したりするので
端末の管理が大変という問題とか開発拠点が離れている場合などもあるのでそこら辺を解消できる。

なぜか使った記憶がありとても便利だった。(元社員だっただけです)

なぜやってみたか

@misyobun さんがやってたのを見て
そういえば弊社CTOのあんちぽさんに「導入しといて」って雑に振られたので
面白そうだし「わかりました」って言ったのを思い出したから
(2週間前くらいだっただろうか…)

さっそく導入

homebrew があると便利なので入れとくといいかと

  • rethinkdb
  • graphicsmagick
  • zeromq
  • protobuf
  • yasm
  • pkg-config

上記をまとめて install

brew install rethinkdb graphicsmagick zeromq protobuf yasm pkg-config

node.js を install

$ brew install node
$ node -v
v5.0.0

stf を install

$ npm install -g stf
...
# node-gyp の install で error が発生した…

調べると node-gyp は最新の node に対応してないとかなんとか
なので node v0.12.7 を入れた

node の uninstall は下記で行う

$ brew uninstall node

もう一度 stf を install

$ npm install -g stf
...
# pkg-config が見つけられないてきな error が発生した…

# PKG_CONFIG_PATH を指定してやる (path は各々の環境に合わせてください)
$ export PKG_CONFIG_PATH=/usr/local/Cellar/zeromq/4.1.3/lib/pkgconfig/
$ npm install -g stf

install 関連は終わり

stf を立ち上げる

まずは rethinkdb から

$ rethinkdb
Recursively removing directory /hoge/rethinkdb_data/tmp
Initializing directory /hoge/rethinkdb_data
Running rethinkdb 2.1.5-2 (CLANG 7.0.0 (clang-700.0.72))...
Running on Darwin 14.5.0 x86_64
Loading data from directory /Users/mac/rethinkdb_data
...
...

stf を立ち上げる
端末はUSBでつないでおく

$ stf local
# ログがいっぱいでる

http://localhost:7100/ にアクセスすると下記のような画面が表示される
f:id:shiro-16:20151103180449p:plain

画像で「停止する」の部分が「準備中」になっていていくら待っても準備が完了しない…

log を見てみるとなにか失敗している

INF/device:resources:service 44364 [hoge] Installing STFService
FTL/device 44364 [hoge] Setup had an error TimeoutError: operation timed out
    at afterTimeout (/usr/local/lib/node_modules/stf/node_modules/adbkit/node_modules/bluebird/js/main/timers.js:11:15)
    at timeoutTimeout (/usr/local/lib/node_modules/stf/node_modules/adbkit/node_modules/bluebird/js/main/timers.js:53:9)
    at Timer.listOnTimeout (timers.js:119:15)

STFService.apk の install が失敗してしまっている様子?
とりあえず手動で STFService.apk を install する
(adb コマンド is 何 って人はググってくれ!)

apk のソースは ここ にあるのでこれを build してもいいと思う

$ adb install /usr/local/lib/node_modules/stf/vendor/STFService/STFService.apk

これで stf を再起動してみたが同じエラーが出てたので USB を一度抜き挿ししたら端末を操作できるようになった。
結果は下記をみてください


最後に

結構簡単にできた。
RethinkDB触ったことないのでちょっといじってみるのは良さそう
実際にこれを会社で導入する場合 server 用意してそれに USB ハブを挿しまくるのだろう。
そこら辺はなんかいい感じに相談してみよう。

やはり便利だ。

Sidekiq の queue を眺める際に使用するコマンドを雑にまとめる

はじめに

前回書いたこの記事を書く際に実際に積まれている queue をあれこれ見ていたのですが、
その際に使ったコマンドを忘れそうだったのでまとめておく。
めんどくさくてまとめなかったわけでは…

shiro-16.hatenablog.com

redis-cli

まずは基本的なこと redis-cli を使って redis のデータを見ることが出来る

Redis server に接続して対話的に実行
$ redis-cli
redis 127.0.0.1:6379> KEYS *
引数を指定して実行
$ redis-cli KEYS '*'

perform_async

※ perform_async で user 3 つ default 2 つ queue を積んだ状態

どんな key が生成されるか
$ $ redis-cli KEYS '*'
1) "queue:default"
2) "queues"
3) "queue:user"
key の member を全て取得
# SMEMBERS key
$ redis-cli SMEMBERS 'queues'
1) "user"
2) "default"
queue の件数を取得
$ redis-cli LLEN "queue:user"
(integer) 3
queue を 1 件取得
# LINDEX index
$ redis-cli LINDEX "queue:user" 0
"{\"class\":\"UserWorker\",\"args\":[1],\"retry\":true,\"queue\":\"user\",\"jid\":\"adddb1f368e7a622225ef315\",\"created_at\":1445260869.8274186,\"enqueued_at\":1445260869.8274736}"
queue を複数件取得
# LRANGE start end
$ redis-cli LRANGE "queue:user" 1 2
1) "{\"class\":\"UserWorker\",\"args\":[1],\"retry\":true,\"queue\":\"user\",\"jid\":\"b009bbcaa2b0dca70201b448\",\"created_at\":1445260841.7604742,\"enqueued_at\":1445260841.760538}"
2) "{\"class\":\"UserWorker\",\"args\":[1],\"retry\":true,\"queue\":\"user\",\"jid\":\"c9d40578849234b9f8b8d429\",\"created_at\":1445260828.8738196,\"enqueued_at\":1445260828.8746564}"

perform_in

※ perform_in で 3 つ queue を積んだ状態

どんな key が生成されるか
$ redis-cli KEYS '*'
1) "schedule"
schedule の member を見る

start と end を指定する

# ZRANGE key start end
$ redis-cli ZRANGE schedule 0 0
1) "{\"class\":\"UserWorker\",\"args\":[1],\"retry\":true,\"queue\":\"default\",\"jid\":\"2b6f8042a496b71128881c12\",\"created_at\":1445259670.319731}"

全て取得する

$ redis-cli ZRANGEBYSCORE schedule -inf +inf
1) "{\"class\":\"UserWorker\",\"args\":[1],\"retry\":true,\"queue\":\"default\",\"jid\":\"2b6f8042a496b71128881c12\",\"created_at\":1445259670.319731}"
2) "{\"class\":\"UserWorker\",\"args\":[1],\"retry\":true,\"queue\":\"default\",\"jid\":\"edc66e38f51e4b405ef2b984\",\"created_at\":1445260137.1156876}"
3) "{\"class\":\"UserWorker\",\"args\":[1],\"retry\":true,\"queue\":\"default\",\"jid\":\"8eb4b0bf44dee20a4c797424\",\"created_at\":1445260138.2186956}"

削除する

# ZREM key member
$ redis-cli ZREM schedule "{\"class\":\"UserWorker\",\"args\":[1],\"retry\":true,\"queue\":\"default\",\"jid\":\"2b6f8042a496b71128881c12\",\"created_at\":1445259670.319731}"

全部消したい!

普通はやらないけど全部のデータを消したい時に使う

$ redis-cli FLUSHALL
OK

最後に

ここら辺が使えれば Sidekiq の Redis 周りのことを調べるには困らないはず!

Sidekiq について基本と1年半運用してのあれこれ

はじめに

実際に運用していた時に非同期にしていた主な処理は下記のようなものがあります。

  • iOS Android の push 通知の送信処理
  • ログの作成
  • 様々な外部 API の呼び出し
  • 非同期で更新しても問題ないデータの更新

Sidekiq is なに

sidekiqは非同期処理を実現する gem
他にも Ruby で非同期処理を実現できる有名な gem には
resque や delayed_job 等がある。

sidekiq.org

Enterprise版等もありますが、
今回はOSS版を使用している前提でのお話しです。

他の非同期処理が可能な gem との簡単な比較

FAQ · mperham/sidekiq Wiki · GitHub
この内容は結構真実を語っていることを最近知った

Sidekiq
  • Redis
  • マルチスレッド
  • リトライ処理あり
  • おしゃれなダッシュボード
Resque
  • Redis
  • ジョブごとにフォーク
  • リトライ処理なし
  • Sidekiqに比べると簡素なダッシュボード
Delayed Job
  • DB(専用テーブル作成)
  • リトライ処理あり
  • delay method が便利
  • 基本的にDBを使うので導入簡単

実装例

Redis は既にセットアップ済みとする

sidekiq を追加

$ vi Gemfile
+ gem 'sidekiq'

$ bundle install

config を追加

$ vi config/sidekiq.yml
:verbose: true
:pidfile: ./tmp/pids/sidekiq.pid
:logfile: ./log/sidekiq.log
:concurrency: 10 # worker process 数
:queues: # 処理するキュー名
  - default
  - user

env による設定の変更方法

production:
  :concurrency: 25
staging:
  :concurrency: 15

下記のように記述することで priority が設定できる

:queues:
  - [user, 2]
  - [default, 1]

worker file を作成

# UserWorker を作成
$ bundle exec rails g sidekiq:worker User
      create  app/workers/user_worker.rb
      create  test/workers/user_worker_test.rb

user_worker を編集
※今回は例としてわかりやすい処理にしています。

$ vim app/workers/user_worker.rb
- def perform(*args)
- # Do something
+ sidekiq_options queue: :user # キュー名指定がない場合は default になる
+ def perform(id, name)
+   user = User.find(id)
+   user.update(name: name)

キューを積む

$ bundle exec rails c
irb> UserWorker.perform_async(1, "test")
=> "f212bd8bae56c79467494ec8"
irb> User.find(1) # この状態ではまだ record が更新されていない
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> #<User id: 1, name: "1", created_at: "2015-10-11 13:13:39", updated_at: "2015-10-11 13:13:50">

Sidekiq を起動する

$ bundle exec sidekiq -C config/sidekiq.yml -d
# ちょっと時間をおいて
$ bundle exec rails c
irb> User.find(1) # name が更新されていることが確認できる
  User Load (0.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
=> #<User id: 1, name: "test", created_at: "2015-10-11 13:13:39", updated_at: "2015-10-11 13:17:14">

これで簡単な実装例はおしまいです。

Sidekiq の enqueue の解説

Sidekiq が Redis にどのように queue を追加するかを解説する。
Sidekiq は使う method によって使う Redis のデータ型が違う

perform_asyncの場合

「セット型」と「リスト型」を使う。

1.セット型で queues という key で各ワーカーのキュー名を member として登録する
(実装例の場合は member に user を指定する)

2.リストの先頭に queue:キュー名 をキーにして string を追加する。
(実装例の場合は queue:user というキー名になる)

3.string は { class: worker class 名, arg: perform_asyncの引数配列, retry: retry機能が有効かのフラグ, queue: キュー名, jid: SecureRandom.hex(12) で生成された job id, created_at: 作成日, enqueued_at: キューに追加した時間 } この Hash を json にしたもの

以下が実装例での string の例

# Hash
{ class: "UserWorker", args: [1, "test"], retry: true, queue: "user", jid: 6284ea2d3637756fc121b8f7, created_at: 1444571406.7752862, enqueued_at: 1444571406.7754705 }

# Json化
"{\"class\":\"UserWorker\",\"args\":[1,\"test\"],\"retry\":true,\"queue\":\"user\",\"jid\":\"6284ea2d3637756fc121b8f7\",\"created_at\":1444571406.7752862,\"enqueued_at\":1444571406.7754705}"

perform_in の場合

「ソート済みセット型」を使う

1. ソート済みセット型で schedule という key で score に 実行時間を指定して member を登録する

2. member は { class: worker class 名, arg: perform_asyncの引数配列, retry: retry機能が有効かのフラグ, queue: キュー名, jid: SecureRandom.hex(12) で生成された job id, created_at: 作成日 } この Hash を json にしたもの

以下が実装例での member の例

# Hash
{ class: "UserWorker", args: [1, "test"], retry: true, queue: "user", jid: 6284ea2d3637756fc121b8f7, created_at: 1444571406.7752862 }

# Json化
"{\"class\":\"UserWorker\",\"args\":[1,\"test\"],\"retry\":true,\"queue\":\"user\",\"jid\":\"6284ea2d3637756fc121b8f7\",\"created_at\":1444571406.7752862}"

Redis について

Sidekiq を使う上で欠かせない Redis ですが、今回の記事で Redis のことまで深く説明すると
だいぶ長い記事になるので別記事として後日公開します。

工夫した点

ここからが本題の知見と言ってもいいかなという部分になります。

1. Redis の構成

当時開発していた Rails のアプリケーションでは、
session, sidekiq, cache に Redis を使用していました。
それぞれ別々の Redis にデータを保存していました。

別々にした理由は下記

  • Redis はオンメモリ型のKVSなので容量的な制約が大きい(実メモリの約半分程度)
  • 複数の用途で使い容量が設定によっては消えて欲しくないものが消える危険
  • 1つの Redis で運用をし後々分割しようと思った際にデータを分けるのが面倒
構成

レプリケーションを組み,Redis Sentinelで自動フェイルオーバーするように設定を行う。
アプリケーション側は下記の記事で書きましたが, gem の redis-sentinel を導入

shiro-16.hatenablog.com

redis-sentinel を導入すると Rails は Redis Sentinel から現在の master 情報を取得し接続、
障害により接続に失敗した場合に 「Redis Sentinel から master 情報を取得し接続」を繰り返し
master が切り替わったタイミングで正常に接続ができるようになるという感じ

2. 引数は出来るだけ少なく

perform_async 等の引数は出来るだけ少なくしましょうという話

例として Twitter でファボられた時に push を送る処理を実装
(実際には1ユーザに複数のtokenが紐づく可能性がある)

# ダメな例
# token: device_token or registration_id
# message: push 内容
def perform(token, message)
   FavoritePush.send(token, message)
end

# 良い例
# id: favorite情報を保存している record の id
def perform(id)
  favorite = Favorite.find(id)
  message = FavoritePush.message(favorite)
  FavoritePush.send(favorite.tweet.user.token, message)
end
何が良いのか?

・Redis の容量の圧迫を軽減出来る
・キューを積んでから実行されるまでに record が更新された場合にも対処出来る(今回の場合 token が更新されて push が送信出来ない問題を回避出来る)
・console 等からキューを積む場合に id を渡すだけなのでシンプル
SQLの発行回数が増えるのですが primary key や index を使用した検索になることが多いと思われるので問題ないかと思われる。
DBが重くなるのであれば Slave を増やせばいいので Redis の容量問題に比べれば微々たるものだし、primary key や index を使用しても重いならそれは設計が(ry
・自分が運用していた時は引数は1〜3つでした。(例外が一部ありましたが)

※ ただし引数が多くなる場合も、勿論あります。

3. 判定処理等を worker 側に持たせる

今回は2の例に push を送信するかどうかを判定する処理を追加する

# ダメな例
def perform(token, message)
  FavoritePush.send(token, message)
end
# キューを積む際に
# PushWorker.perform_async(favorite.tweet.user.token, FavoritePush.message(favorite)) if favorite.tweet.user.send_push?


# 良い例
def perform(id)
  favorite = Favorite.find(id)
  return unless favorite.tweet.user.send_push?
  message = FavoritePush.message(favorite)
  FavoritePush.send(favorite.tweet.user.token, message)
end
何が良いのか?

今回の場合はシンプルな判定だが、もっと複雑な判定を行う場面は多い
そうなった場合に特に有効

・キューを積む際に判定するより同期処理側の処理速度は速くなる
・今回の場合は message を生成する処理も worker 側で行うので同期処理側の処理速度は速くなる
・console 等からキューを積む場合に判定内容を気にしなくて良くなる

※ Redis に積むキューの数自体は増えてしまうので Redis の使用量は増えてしまいます

4. retry 機能に注意する

Sidekiq には retry 機能があるのでそのことを念頭に置いて実装を行う必要がある。
push 送信の処理に送信済みかフラグを持たせる

def perform(id)
  favorite = Favorite.find(id)
  return unless favorite.tweet.user.send_push?
  message = FavoritePush.message(favorite)
  FavoritePush.send(favorite.tweet.user.token, message)
  favorite.update(send_push: true)
end

retry 機能があるのでもし favorite.update でエラーが起こった場合
retry されて再度実行されます。
なので favorite.update が正常に終了するまで同じ内容の push を送信し続けることになってしまいます。

例外をうまく扱うか update を別 worker として実装し push 送信後にキューを積む等の工夫が必要

※ retry を個別に off にすることも可能

5. record が削除されている場合も考慮する

Sidekiq だけの話ではないですが、
非同期処理なので処理が実行される際には既に対象の record が削除されている可能性も考えなければなりません。
4.の retry の話を念頭に置いて ActiveRecord::RecordNotFound 等の例外を上手く処理する必要があります。

6. batch 処理

「3.判定処理等を worker 側に持たせる」と同じような内容になるのですが、
batch 等であるテーブルの各 record に対して複雑な処理をする場合、
処理は全て worker 側で行ってしまおうということです。

例)全ユーザを対象に何かしらの計算を処理を行う batch があるとする

# ダメな例
User.find_each do |user|
  # 複雑な処理

  UserWorker.perform_async(user.id, result)
end
class UserWorker
  def perform(id, result)
    user = User.find(id)
    user.update(result: result)
  end
end

# いい例
User.select(:id).find_each do |user|
  UserWorker.perform_async(user.id)
end

class UserWorker
  def perform(id)
    user = User.find(id)
    # 複雑な処理

    user.update(result: result)
  end
end
良い点

・時間がかかる複雑な処理をマルチスレッドで行うことで処理速度が上がる

deploy

deployに関しては下記のページを参考にするのが良さそう
Deployment · mperham/sidekiq Wiki · GitHub

その他

Best Practices · mperham/sidekiq Wiki · GitHub
ここら辺も合わせて読むと良いかと

最後に

なぜこのような記事にまとめようと思ったのかというと
前々からまとめておこうとは思ったのですが、
最近 Sidekiq を使用していないので忘れてしまいそうだったことと、
最近 Sidekiq 感覚で Delayed Job を使用したら少々痛い目を見たという
辛い経験があったので非同期処理についてまとめておこうといった感じです。

また、ここに書いてあることが全て正しいわけではなく
自分の開発していたアプリケーションにはこのパターンが良かったというだけで、
これに沿ったからといって問題が全て解決するというわけではないと思います。

Sidekiq と Redis の特徴を理解して上手く付き合っていくのが良いかと思います。

自分は Sidekiq 好きなので贔屓目の記事になっているかもしれません。

表参道.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を知った時に下記のような感想を持っていました。
なのでとても楽しく開発できたし、少しても関われることができありがたいという思いです。