今年になってから、再びrvmの利用を始めた。最近のrvmは、 cd 後に走るフックを定義できるようなので、何度も試みている bundle exec 付きコマンド実行の省力化に挑戦する。

とは言っても、そのへんはrvm側でも意識するようになっていて、安定版にも after_cd_bundler というフックスクリプトが用意されている。このスクリプトは、bundle コマンドを --binstubs オプション付きで実行することを前提としていて、 PATH の先頭にスタブをインストールしたディレクトリを追加したり取り除いたりするという動作になっている。

最近は--binstubsを使っていないので、代わりにこんなスクリプトを書いてみた。


#!/bin/zsh

if [[ Gemfile.lock -nt Gemfile ]]; then
  for bin in $(ruby -rbundler/setup -e 'Bundler.setup' -e 'puts $:.map{|d| Dir["#{d}/../bin/*"] }.flatten.map{|f| File.basename(f)}'); do
    [[ $bin = bundle ]] || alias $bin='bundle exec '$bin
  done
else
  for alias in $(alias | sed -n -e "s/='bundle exec .*'//p"); do
    unalias "$alias"
  done
fi

※ 先頭のsh-bangはエディタにzshを認識させるもので、直接実行するわけではない。

Gemfile.lockとGemfileが両方存在して、Gemfile.lockのほうが新しい場合に、Bundler環境下で利用可能となるbinディレクトリの下のコマンドを拾い出し、bundle exec付きのエイリアスを作っている。逆に条件を満たさなければbundle exec付きの定義になっているエイリアスを一通り削除。

親ディレクトリにGemfileがある場合も考慮すべきじゃないかと思いはするが、とりあえず現在の仕様でしばらく使ってみよう。

  1. sakuro posted this