表参道.rb #4で「本当は怖い オープンクラスと Duck Typing」というLTをやった話
スライドです
本当は怖いオープンクラスとDuckTyping - 表参道.rb #4
まぁたいした話じゃないんですが、マッドマックスの画像をスクリーンに大写しできたのでその点だけで個人的には満足しています
「型を讃えよ」
ぼくのかんがえたさいきょうのGit Repository Browser: Gitterb をRuby2.1.2/Rails4にupgradeしてDockerImage作った話
3年ほど前に、GitterbというGitリポジトリのコミットログを可視化するツールを作った。
このアプリケーションはRuby1.9/Rails3.2 で書かれていて、今となってはもう動かないので、Ruby2.1/Rails4へupgradeした。
デモサイトはこちら http://gitterb.yuroyoro.net/
依存しているGritというRubyからGitリポジトリをホゲるGemがRuby2系では動かないので、libgit2のRubyバインディングであるRuggedに移行している。
あと、せっかくなのでCentOS7で動くDockerImageを作った。Docker Hubにおいてある。
以下のようにdocker pullした後にrunすると、port3000でサンプルが起動する。
docker pull yuroyoro/gitterb docker run -d -p 3000:3000 -t yuroyoro/gitterb
macでboot2dcoker使ってる人は、port forwardingしてくだされ。
ssh -N -L 3000:127.0.0.1:3000 docker@localhost -p 2022
( ꒪⌓꒪) あばばばばばばばば
Rails3でMultiJsonのBackendをyajlに変更してJSONのエンコード/デコードのパフォーマンスを改善する
yajl(Yet Another JSON Library)っていう高速なJSONライブラリがあって、
こいつをrubyから使えるようにするyajl-rubyってgemがあって、これをMultiJsonのBackendに変更することで、RailsにおけるJSON処理の高速化が期待できるデス。
素のjson.gemと、yajl-rubyとで適当なActiveRecordオブジェクトからJSONへのエンコードと、その逆のデコードで簡単にベンチってみると、約2倍の差があることが分かる。
-------------------------------------------------------------------------------- Benchmark of json encoding/decoding json_gem vs yajl -------------------------------------------------------------------------------- | json_gem | yajl | json_gem/yajl | --Single ActiveRecord Object ----------------------------------------------------- encode x10000 | 12.130 | 6.167 | 1.97x | decode x10000 | 1.085 | 0.437 | 2.48x | --Array ActiveRecord Objects----------------------------------------------------- encode x10000 | 508.319 | 225.235 | 2.26x | decode x10000 | 39.069 | 19.869 | 1.97x |
MultiJsonのBackendをyajlに変えたら素のjson.gemの2倍のパフォーマンスになった件
MultiJsonは、yajl-rubyがあると自動的にそっちを見るようになってるので、gem 'yajl-ruby'するだけでjsonの処理が高速化する、とおもいきや……
ActiveSupport::JSONのコードを見てみると、JSONのデコード時にはMultiJsonを利用するようになっているが、エンコードする際にはActiveSupport独自の実装でエンコードするようになっている。この理由としては、ActiveSupportのAPIと他のライブラリの実装で互換性がないかもしれない、という話みたいだ。
Endoding with yajl-ruby for rails 3 · Issue #40 · brianmario/yajl-ruby · GitHub
とはいえ、オブジェクトをActiveSupportのas_jsonでHashにしてしまって、それをyajlでJSONにエンコードすれば問題ないはず。ということで、このようなパッチを書いた。
MultiJson.engine = :yajl unless MultiJson.engine == MultiJson::Adapters::Yajl module ActiveSupport module JSON def self.encode(value, options = nil) hash = ActiveSupport::JSON::Encoding::Encoder.new(options).as_json(value) MultiJson.encode(hash) end end end
JSONを大量にやりとりする系のアプリケーションには多少のパフォーマンス改善が期待できる、はず。
Railsで今いるブランチによってデータベースを切り替える
ブランチングモデルとしてgit-flowを使っていて、メインラインとして、本番適用中のmasterブランチと、次期リリース用のrelease/9999ブランチと、メイン開発ブランチのdevelopがある。
ところが、開発中は頻繁にブランチを移動するし、ブランチによってDBのスキーマが異なるなんてザラにあるし、ブランチ切り替える度にconfig/database.ymlを書き換えるのもタルいので、こんな風に書いた。
development: adapter: postgresql database: my_app_<%= case `git symbolic-ref --short HEAD` when 'master' then 'master' when 'develop' then 'develop' when /release\/.*/ then 'release' when /hotfix\/.*/ then 'master' when /feature\/.*/ then 'develop' else 'develop' end %> username: yuroyoro password: yuroyoro host: localhost encoding: utf8
これで、masterブランチにいるときはmy_app_masterというDBを使い、release/9999ブランチの時はmy_app_releaseってDBを使うようになる。migrationが入り乱れたり、アプリケーションとスキーマが合わないので500るとかなくなって凄惨性あがる.
ちょっとの手間でRSpecの出力をキレイにするためにnamed_letというのを書いてみた
RSpecの話です。
RSpecは、テストコードがそのまま仕様を記述するドキュメントになる、というのが大きな利点の一つです。
しかし、rspecコマンドに-dオプションを渡して出力されるドキュメントは、必ずしも読める文章になっているとは限りません。
例として、以下のようなCanCanのspecを見てみます。
require 'spec_helper' require "cancan/matchers" describe Ability do context 'an user' do let(:user) { Factory.create(:user) } let(:article) { Factory.create(:article) } let(:own_article) { Factory.create(:article, :user => user) } subject { Ability.new(user) } it { should be_able_to(:read, article) } it { should be_able_to(:update, own_article) } end end
Userは、ある記事をreadする権限を持っていて、自分が書いた記事はupdateすることができる、という記述です。
'should be_able_to(:read, article)'や' should be_able_to(:update, own_article) 'は、そのままの文章になってます。
では、これをrspec -dで実行してみます。
アルェ?
'should be able to :read #
describe Ability do context 'an user' do let(:user) { Factory.create(:user) } named_let(:article) { Factory.create(:article) } named_let(:own_article, "own article") { Factory.create(:article, :user => user) } subject { Ability.new(user) } it { should be_able_to(:read, article) } it { should be_able_to(:update, own_article) } end end
さっきのspecで、letで定義されていたarticleを、named_letを利用するように変更しました。named_letでは、第一引数のSymbolを表示の際に利用します。第二引数に別名を渡すことも出来ます。
named_let(:article) { Factory.create(:article) } named_let(:own_article, "own article") { Factory.create(:article, :user => user) }
あらためて実行してみます。
ちゃんと意図した文章になって出力されていますね。やったー。
ぼくのかんがえたさいきょうのGit Repository Browser
こんなヤツ
デモサイトはこちら http://gitterb.yuroyoro.net/
Gitである程度運用してると、ブランチがいっぱいになっていつどこから生えたのかわからなくなったり、どのブランチがマージされてるか把握できなかったりとかがあると思う。
たとえばgit log --graph とかgit merge-baseとかコマンドで頑張ればいいんだけど、俺はあまり頭良くないし記憶力もないので、コミットのつながりをグラフィカルに表示してほしいと常々思っていたわけ。
たとえばGitXとかgitkとかGit Towerとかのツリー表示って、こんな感じじゃないですか。
これはこれでまぁいいんだけど、この程度ならlog --graphやtigを使えばいいのでわざわざGUI起動するまでもないし、そもそもあんまりグラフィカルじゃない。見たいのは、Pro Gitとかにあるようなコミットを○と矢印でつないだ有向グラフな図なんだよ。
で、あんまりにもないので作った。
Ruby1.9.2とRails3.0.9で動作確認してる。多分Ruby1.8.7/Rails2.3でも動くと思うけど確認してない。
LGPLなライセンスで。テストは、書いてない。pull request歓迎します。
セットアップ
pygementが必要なのでeasy_installでいれろ
sudo easy_install pygments
Bundler使って依存Gem入れろ
gem install bundler # if you haven't bundle install ./vendor/bundle
config/database.ymlに表示するgitリポジトリを絶対パスで指定しる
development: repository: '/home/your_name/your_repository'
サーバ起動して、'http://localhsost:3000'で表示させり
script/rails server
使い方的なアレ
とりあえず最初はmasterからさかのぼって100件分のコミットを出す。一緒に、表示されているコミットに到達可能なブランチとそのコミットもだす。これは'all'チェックボックスをoffると消える。
赤い時の四角がブランチで、青いのがtagな。
git log --graph --all的なイメージで表示してると思え。思え。
フォーカスするブランチを切り替えたいならプルダウンから選べばいいんじゃない?好きにすれば?
○で表示してるのがコミットオブジェクトな。マウス乗せるとコミットログをポップアップさせる。させる。
クリックすると、そのコミットの詳細が出る。ダブルクリックすると消える。以上。
できないこと
複数のリポジトリを切り替えたり- リモートのブランチを出したり(fetchしろ)
- comitしたりpullしたりrebaseしたりpushしたり(そういうのはもっと高機能なGUIツールでやるのがいいとおもいます)