| @技術/プログラミング

以前は電車の本数多いところに住んでたので帰りの電車の時間とか気にしたことなかったけど、いまは郊外に住んでるので電車の本数少なくて、一本乗り遅れると駅で 20 分待たされたりする。特に遅くまで仕事してたりすると電車の本数がみるみる少なくなる。なので乗るべき電車に乗り遅れないように Yahoo! 乗換案内の通勤タイマーをよく使ってる。家まで帰る電車の発車時刻まであと何分かがカウントダウン表示されて便利。

ただ iPhone のウィジェットで見るとちょっともっさりしててだるい。 Pebble とかでサクッと確認できないかと思っているけど Pebble 入手して 10 ヶ月以上経つにもかかわらず Pebble 用のソフトを自分で作るという機運が高まらず今日に至る。

ある晩ふと、これって BitBar でできるんじゃねと思った。 BitBar は Mac のメニューバーに CLI で出力される情報を表示されることができるソフトで、 Netatmo Weather Station の計測値を表示するのに使っている。 Mac のメニューバーから二酸化炭素濃度や湿度確認できて便利。こんな感じ。これの通勤タイマー版が欲しい。

取り急ぎ時刻表の情報必要だけどちょっと探した感じでは簡単に時刻表取れるような API なかった。ので Yahoo! 乗換案内の時刻表をダウンロードして pup というコマンドラインの HTML パーサーで JSON 化し、それを jq に食わせて整形して良い感じの JSON にするという風にした。

# curl して HTML 取得
curl -s http://transit.yahoo.co.jp/station/time/28236/?gid=6400 | \
# HTML から必要な情報取り出して JSON 化
pup 'table.tblDiaDetail [id*="hh_"] json{}' | \
# JSON を良い感じに整形
jq '[.[] | { hour: .children[0].text, minutes: [.children[1].children[].children[].children[].children[].children | map(.text) | join(" ") ] }]'

得られる JSON はこんなのになる。(福岡市地下鉄空港線天神駅の姪浜方面の時刻一覧)

[
  {
    "hour": "5",
    "minutes": [
      "36",
      "42",
      "56 筑"
    ]
  },
  {
    "hour": "6",
    "minutes": [
      "8",
      "12 筑",
      "17",
      "26 筑",
      "34",
      "39",
      "43 筑",
      "56 筑"
    ]
  },
  ...,
  {
    "hour": "24",
    "minutes": [
      "6",
      "12 筑"
    ]
  }
]

これをコマンドラインで良い感じに表示するスクリプトを Ruby なり Shell Script なりで書いて BitBar に登録すればメニューバーから次の電車を確認できるようになり便利。

| @技術/プログラミング

京都国際会館

京都であった RubyKaigi 2016 を観覧してきた。 RubyKaigi 、つくばであった 2010 がこれまでの人生での唯一の RubyKaigi で、人生二度目の観覧だった。

RubyKaigi 2010 の思い出

一度目のときは少し前に増田に上がってた勉強会ゴロ状態(受付の人と技術書を買ったジュンク堂の人と以外誰とも会話をせずに帰宅)だった。

ちなみにこのとき ESM の企業発表を見に行って、 ESM に転職したばかりの hsbt さんの姿を初めて目にした。なんか入社したばかりなのに社内ブログで暴れてて愉快、みたいな紹介のされ方だった。その後同じ会社で働くことになるとは思いもしなかった。

ESM の発表はとにかく鮮烈に印象に残ってて、ペアプロのライブコーディングだった。 ursm さんが CRM か何かの開発を実演してた。まず最初に落ちるテストコードを書いて、その後にパスするプロダクトコードを書く、というやつを初めて目にして、田舎で HTML コーダーをしつつちょっとしたプログラムを書いてた自分は衝撃を受けた。黒い画面の Vim で高速にコードを書いていく様がとにかくかっこよかった。はやくこういう感じでコード書けるようになりたい、と思ったものだった。

クックパッドの企業発表みたいのも聞きにいって、このときクックパッドもまだそんなにエンジニアの数多くなかったはずで、同じくはてなから転職してきたばかりのセコンさんが話してるのを聞いてトートバッグもらって帰った。

YAPC::Asia Tokyo 2015 の思い出

去年の夏、 YAPC で東京に行って、このときはペ社時代の知ってる人としゃべったりして無言の帰宅は避けられた。

YAPC 2015 は気がついたときには懇親会の申し込み締め切られててどこにも行けず、一人浜松町の宿泊先の近くの「とにかく安くて量が多い」と食べログにレビューが書いてある寿司屋に入って一人で寿司を食べたら寿司がねちゃっとしてて具合が悪くなったりしてた。

RubyKaigi 2016

今年も発表する側にまわったわけではないので一般ピープルである点は同じだったが、これまで話したことなかった人と話せたのがよかった。

取り分けよかったのが Fjord 社の komagata さんと話せたことだった。今後の Lokka の方針をどうするか開発者会議的なものを開催してババっと方針を決めましょう、という話をした。 Lokka 、思い入れがあるので積極的にメンテナンスに関わって今後も長く使い続けていきたい。

一日目

一日目は Kaizen Chat についてのブログ記事を公開するというタスクがあって、 Matz のキーノートとかはあまりじっくり聞けなかった。記事公開後に会社のブースで自分のシールを配布したりして公私混同してた。

今年の RubyKaigi は懇親会の枠が大きかったおかげで申し込みそびれるということにならなくてよかった。

オフィシャル懇親会で Fusic 社の k1low さんと初めてゆっくり話をした。Fukuoka.rb で顔を合わせることあっても一緒に酒飲んだりする機会なかったので RubyKaigi に来て初めてじっくり話すという感じだった。

ヒトデさんとその愉快な仲間たちの皆さんとも話して、 shikakun はオリジン弁当ばかり食べてるくせにやたら調理器具を持っていて不可解だとか、風呂蓋付きの浴室がある部屋にすんでいていけすかないという話をした。

Twitter で 8 年くらい前にハゲクラスタとしてわいわいやってた send_ さんとも再会できて、お互い帽子をかぶった状態でいまの仕事の話をしたりした。

オフィシャル懇親会のあとは、ヒトデさんオーガナイズの二次会に参加させてもらった。デンエンという物価が崩壊してる飲み屋に行ってタワーから注いで飲むビール飲みまくった。クックパッド社の著名エンジニアの皆さんと対面に座ったけど人に自慢できるような OSS とかなくて雑魚いので自己紹介に困ったが、とりあえずこういうアイコンのものですと言ってシールを見せたら「あ、なんか見たことある」という感じになったのでシール便利だった。

二日目

朝一番の Justin Searls さんのリファクタリングについての発表がとにかく面白かった。

去年 YAPC で GitHub の人が話してた sicientist と似てるけど、リファクタリング前後のコードで A/B テストをする gem の紹介。新しい方のメソッドが例外投げたら rescue して古い方のメソッドを実行するというのが面白かった。本番にも安心して投入できるとのこと。

三日目

午前二番目に tkawa さんの HTTP クライアントについての発表聞いた。 HTTP クライアント乱立しててひどい、 API をラップしてリモートサーバー側のクラスを再現するような異常なクライアント多くて、 REST API とは一体何なのか状態だ、みたいな話だった。言われてみれば確かにそうかもしれない。独自の API クライアント作ることなく、 Rack が Rack Middleware を use して拡張していくみたいに、 HTTP クライアントの側でも Middleware を use していくのがよい、そこで Faraday ですよ、という話で、あ、 Faraday ってそういうことを目的にしてたんだと膝を打った。

午前中最後の Chris Arcand 氏の発表が面白かった。

Ruby のコードを解析して呼ばれてないメソッドを調べる、という発表だった。実際に Rails プロジェクトとかで使うのは大変そうに見えたけどいまから君のプロジェクトに投入できるよ、 Rails もダイジョブみたいなことを言ってた気がするのでスライド見直したい。

最後のセッションの前、一日目のデンエン会で知古を得た pastak さん見かけたので uiureo さんを紹介してもらって話をした。 uiureo さん、初対面だけど話しやすくて好青年な感じだった。 r7kamura さんとも少ししゃべらせてもらってよかった。

飛行機の時間の都合があったのでクロージングまでは残らず、最後のキーノートの途中で離席して帰途についた。ホールを出ようとしたところで滑り込みで会場にやってきた元同僚の hisaichi551 さんと邂逅して自分のシールを何枚か雑に渡した。ゆっくり話がしたかった。

京都での開催について

京都での開催良かった。個人的には福岡からだと東京に行くよりも京都の方が近いので移動が楽で良い。首都圏からの大多数の参加者も京都に宿泊して参加するので夜通しどこかで RubyKaigi 関連の飲み会が開かれてる感じで祝祭感あった。夕方から観光したりできて海外からの参加者も満足度高いのではないかと思う。京都国際会館のインフラも素晴らしかった(施設、庭園、食事内容)。スポンサーの提供で振る舞われたお弁当おいしかった。

総合的な感想

RubyKaigi 、海外からのスピーカーの発表はどうやってよいコードを書くかとかリファクタリングとかの話が多い。日本人の発表者の人は Ruby を開発する方の話が多い。( Ruby コミッターのほとんどが日本人だから)。なので Ruby 本体の開発に興味ない人( Ruby 開発者ではなく Ruby ユーザーなプログラマー)はぽかんとすることが多いかもしれない。自分は結構ぽかんとしてた。

あと今回多いと感じたのが Concurrency についての話だった。どうやって Ruby で並行性を上げるかという話。 Thread は難しいので素人は手を出すな、ということはわかったけど Ruby 3 の Guild というので素人でも Concurrent なプログラムが書けるようになるかどうかは今ひとつわからなかったので資料を読み直したい( reuibld.fm の Episode 158 を聞くと良い復習になりそう)。 Ruby 3 に並行処理の使い勝手が向上する前に、他の言語で並行処理について学んで準備をしといた方が良さそうだと感じた。

2010年の勉強会ゴロ状態のときに比べれば、何人かの人と話したりシールを配ったりすることができて、有意義な時間を過ごすことができたと思う。ただアイコンの気持ち悪さで認知されるよりも書いたソフトウェアの知名度で認知される方がよいので、カンファレンスに行って自己紹介するときに「○×というソフトを作ってます」と言えるようになりたい。仕事だけじゃなく、オープンソース活動もやっていけるように頑張りたいな、と気持ちをあらたにした会でした。

| @技術/プログラミング

@glidenote 先生作の memolist.vim 便利で、仕事のドキュメントからメモ書き、ポエムに至るまで memolist.vim で書いてるけど、 ~/Dropbox/memolist/ にドキュメントが溜まりまくって厳しい感じになってきてた。文章を書く、ということに関しては vim + memolist.vim はとても良いのだけど、書いたものを後から読み直す、という面では弱い部分があると感じる。 iPhone で読みづらいし。その点、 Day One は過去記事を読みやすいし、 iPhone アプリもあるので夜寝る前に過去に書いた文章を読んでニヤニヤしながら眠ることも出来る[1]。

というわけで ~/Dropbox/memolist/ にある Markdown のファイルを Day One.app ( Day One 2)に取り込むやつを書いた。

タイトルにマッチする文字列が入ったファイルを除外したり、その日以降のやつだけ、という感じで絞り込み指定したりできる。めっちゃ便利。

使い方

rb-dayonejson gem が必要なのでインストールしてください。 --execute オプションを付けないとデフォルトは dry-run です。

Example) 今日書いた記事をインポートする

ruby memolist2dayone.rb

Example) 2015/01/01 以降の記事を取り込むが、「日報」という文字列をタイトルに含む記事は除外する

ruby memolist2dayone.rb --since 2015/01/01 --exclude 日報

Example) ~/Dropbox/memolist 以外のディレクトリを対象ディレクトリにしたいとき

ruby memolist2dayone.rb --target_dir ~/memolist/

[1]: 前も似たような記事書いてる。 昔の日記を全部 Day One.app にぶっ込んだ - portal shit!

| @技術/プログラミング

昨日飲みに行って今朝起きてからふとコード書きたくなって、アドベントカレンダーもあることだし(去年の Adventar で自分のブログだけ og:image がなくて画像が出てなくて残念だった)、このブログを Open Graph protocol に対応させることにした。

Twitter Card の Lokka Plugin を前作ってたのでそれを改造した。

Ruby 2.1.0 以降で使える Module#refine 使いまくったけど安全にモンキーパッチできて便利。

module AddImagesToEntry
  refine Entry do
    def images
      self.body.scan(/https?:\/\/[\w\/:%#\$&\?\(\)~\.=\+\-]+?\.(?:png|jpe?g|gif)/)
    end
  end
end

refine するときのモジュール名、 ActiveRecord のマイグレーションのクラス名みたいで面白い。

| @技術/プログラミング

このブログの Archive ページ自分で作った Lokka Plugin でできているのだけど、ここを React を使って作ってみた。 React チュートリアルの写経の題材を自分のブログにした感じ。 CoffeeScript オワコンと言われて久しいけど Coffee で書いた。 JSX を CoffeeScript で書くときはバッククオートで囲むとよいという知見が得られた。

Entry = React.createClass
  render: ->
    `(
      <li className="entry">
        <a href={this.props.link}>{this.props.title}</a>
        <div className="detail-information">
          <span className="created_at">{this.props.created_at}</span>
          <Category category={this.props.category} />
        </div>
      </li>
    )`

| @技術/プログラミング

Rails 、初心者にとってもよいフレームワークだと思う。いろいろ学びがある。ただ、なんとかスクールとかで金払って習うのではなくて、 DHH が書いてる『 Rails によるアジャイル Web アプリケーション開発』を読むのがよいと思う。あの本はコラム欄に Rails の裏側の思想とかが書いてある。なんとかスクールで習うのだと最速で Twitter クローンを作るだとか、 Rails の使い方しか身につかないのではないかと想像する。なぜ Rails はその様に作られてるのか、その裏側にある考え方は何か、まで合わせて学べばかなり色んなことが勉強できる。 Rails を使うようになって 5 年くらいになるけど、いまだに毎日発見がある。

| @技術/プログラミング

memolist.vim のデフォルトのテンプレートが挿入する YAML Frontmatter なんか変わってて、 Jekyll のと違った。 Markdown のプレビューは Marked 2 で見るようにしてるんだけど、 Marked 2 は memolist の特殊 YAML Frontmatter を正しく処理してくれない。 YAML Frontmatter はメタ情報なのでプレビュー時には表示して欲しくない( Marked 2 には YAML Frontmatter を表示しないオプションがある)んだけど必ず表示されてしまう。具体的にはこうなる。

調べてみたら memolist には標準のテンプレート以外に自分の好きなテンプレートを設定できる機能あったので、 ~/.vim/template/memolist/markdown.txt というファイル置いて以下のようにしておいた。なお memolist はテンプレート用ディレクトリに置いてある 拡張子.txt というファイルをテンプレートして利用するようだった。なので Markdown 用のテンプレートは markdown.txt となる。

---
title: {{_title_}}
date: {{_date_}}
tags: [{{_tags_}}]
categories: [{{_categories_}}]
---

テンプレートを変更した上で Marked 2 で YAML Frontmatter を Ignore するよう設定する。

すると以下のような表示になる。すっきりする。

すでに過去に書いた記事の YAML Frontmatter も Jekyll のやつに直す雑なスクリプト書いて直しておいた。

files = Dir.glob("#{ENV['HOME']}/Dropbox/memolist/*.markdown")
files.each_with_index do |file, index|
  filename = File.basename(file)
  filepath = File.expand_path(file)
  flag = true

  lines = File.readlines(file)
  lines[0..5].each_with_index do |line, i|
    case
    when line =~ /^title:(.+)/
      lines[i] = "---\n#{line}"
    when line == "==========\n"
      lines[i] = nil
    when line =~/^(?:date|tags|categories|tags):/
      # do nothing
    when line == "- - -\n"
      lines[i] = line.gsub(' ', '')
    else
      flag = false
      next
    end
  end

  if flag
    p filename
    File.write(filepath, lines.compact.join(""))
  end
end