既存のGemをカスタマイズして使うスマートなやり方

Gemを使ってて不便を感じたりしたら自分用にカスタマイズして使うことを最近覚えた。
GitHubにソースが上がっているならば、カスタマイズしたGemを通常のGemと同じようにRubyGemsの仕組みに乗せて利用できる。割と簡単に。

備忘録的に流れを整理しておく。

リポジトリをフォークする

GitHubに自分のアカウントを作って、該当Gemのリポジトリに行って、「Fork」をポチッと押す。
詳しくはGitHubのヘルプを。

カスタマイズする

フォークしたリポジトリをcloneしてきて思い通りに修正。

$ git clone git@github.com:akahigeg/hogehoge.git

後々のことを考えると変更前にトピックブランチを切っておくのがオススメ。

インストールする

ここからが肝。
インストールの際に少しオプションを追加することで、カスタマイズしたGemを通常のGemと遜色なく使用できる。

Gemfile

Gemfileでは以下のようにカスタマイズしたソースが入ったリポジトリを指定する。

gem 'hogehoge', :github => 'akahigeg/hogehoge'

ブランチも指定できる。

gem 'hogehoge', :github => 'akahigeg/hogehoge', branch => 'awesome-feature'

修正中の動作確認などはいちいちpushするのがめんどくさいので、ローカルから読むのが便利。(今日みたいにGitHubさんがユニコーン大量発生で死んでる時もあるし)

gem 'hogehoge', :git => '/Users/akahige/works/hogehoge'

コミットすらめんどくさいならpathの指定でも。

gem 'hogehoge', :path => '/Users/akahige/works/hogehoge'

とはいえ最終的にはGitHubなりどこかのリポジトリに上げてしまった方がいろんな環境から使えて便利ですよ。

gemコマンド

specific_installなるGemを使うとgemコマンドでもカスタマイズしたgemを入れることができるようになる。

$ gem specific_install -l http://github.com/akahigeg/hogehoge.git

なお0.2.4からはGitHubのリポジトリであれば以下のようなショートカット指定ができるようになるようだ。

$ gem specific_install -l akahigeg/hogehoge

同様にgit_installというショートカットも有効になる。

$ gem git_install -l akahigeg/hogehoge

まだリリースされていないが、ここでspecific_installを使えば0.2.4を入れることができる。

$ gem specific_install -l https://github.com/rdp/specific_install.git

まあリリースされていないと言うことは何か問題があるのかもしれないけど。

上流の変更をマージする

元のGemのバージョンアップで便利な機能が追加された場合などは内容を自分のフォークにも反映させたい。
そのやり方はGitHubのヘルプに載っている通り。

Fork A Repo · GitHub Help

$ git remote add upstream https://github.com/octocat/Spoon-Knife.git
$ git fetch upstream
$ git merge upstream/master

コンフリクトしない限りはカスタマイズ内容を維持したまま最新バージョンを使うことができる。
ただこれだと常に開発中の最新版になってしまうので、より安定を求めるならリリースブランチの指定などきめ細かくやった方がいいのかもしれない。

ともあれバージョンアップするたびに再度カスタマイズするのはだるいので、この設定は必須と言える。

もちろんバージョンアップ内容が気にくわなかったり、必要なければ取り込まないという選択もあり。

プルリクエストを送る

カスタマイズ内容を喜んでくれる人が他にもいそうであればプルリクエストを送ってみると良い。
少しめんどくさいけど、採用されれば自分も上流の変更のマージなどのメンテから解放されて後々楽になる、と考えると試みる価値がある。

この時のためにきちんとトピックブランチを切っておくと送りやすい。と思う。

反応がなかったり拒否されても泣かない。
まあ、採用されなければ自分だけでもくもくと使えばいいだけです。

おまけ: GitHubにGemのリポジトリがない場合

GitHubで管理されていないGemのソースは自前でGitHubに上げてしまえば上記の流れに乗せられる。

ただしリポジトリがそのままの名前だと本家のリポジトリと勘違いされてしまうの紛らわしい。なのでリポジトリの名前は変えた方がいいかもしれない。

参考