spring は最近流行ってるので、既に知ってる方もいると思いますが Rails のプリローダーです。
Rails を使ってる人だったら bundle exec rails console
とか bundle exec rails generate model user
とか bundle exec rake routes
とか、便利コマンドにお世話になることも多いと思います。
でも Rails ってとても巨大なフレームワークなので、コマンド一つ起動するにも Rails の資産が全部ロードされて結構な時間がかかります。なので Rails をあらかじめバックグラウンドで起動しておくことによって、コマンドの起動時間を大幅に短縮してくれるのが spring です。
前は Gemfile には書かずにシステムに gem コマンドでインストールして spring rake routes
とかやってて、コマンドの前に spring
と書かないといけないのダルかったのですが、公式のドキュメントを読んでいると最近はまた便利になってるみたいです。
github の README では Rails 4 と Rail 3.2 が対象となっていますが、この記事は Rails 4 前提で書いています。
spring のインストール
最新の spring は Gemfile に書きます。
group :development, :test do
gem 'spring'
end
で
$ bundle install
$ bundle exec spring binstub --all
これで spring が使えるようになります。この時 bin/spring
というファイルが出来ており、また bin/rake
と bin/rails
の先頭に以下のような行が追加されています。
begin
load File.expand_path("../spring", __FILE__)
rescue LoadError
end
これで spring をロードするみたいで、ただし spring がない環境でも問題ないように spring が存在しなければ例外を握りつぶして本来のコマンド起動に進むようです。
spring の使い方
bundle exec
で実行せずに bin/
以下のコマンドから実行します。つまり
$ bin/rake routes
とします。初回起動の時だけ Rails アプリケーションがロードされるのでいつもと同じように時間はかかりますが 2 回目以降はロードされたアプリケーションが利用されるので、起動時間が劇的に改善されています。
1 回目
$ time bin/rake routes
...
bin/rake routes 0.11s user 0.06s system 3% cpu 5.009 total
2 回目
$ time bin/rake routes
...
bin/rake routes 0.11s user 0.05s system 26% cpu 0.599 total
1 回目は 5 秒かかっていますが 2 回目は 0.5 秒になっています。
また bin/spring status
を実行すると現在の spring の起動状況を確認できます。
$ bin/spring status
Spring is running:
2507 spring server | web_app | started 8 mins ago
2508 spring app | web_app | started 8 mins ago | development mode
起動している spring は Rails に再起動が必要なファイル(例えば config/application.rb
など)が変更されると、それを検知して自動的に再起動する仕組みになっています。起動ファイルの読み込みに関しては気にする必要はないので、とても便利です。
direnv のインストール
これで各コマンドの起動が早くなって嬉しいのですが、どのコマンドも最初に bin/
を入力しないといけないので、まだダルさは残ってます。Rails の bin/
ディレクトリを PATH に追加すればいいのですが、その Rails のプロジェクト外ではそのパスは不要なのでむやみに追加するのもはばかられます。
そこで spring の README でも推していますが direnv の登場です。
これは、パス毎に異なる環境変数をロードすることができるもので、これを使えば spring 入りの Rails プロジェクトのディレクトリに移動した時は PATH に Rails の bin/
を追加して、そのディレクトリから出たら PATH は元の値に戻る、というような挙動をさせることが出来ます。
Mac の場合 Homebrew を使えば簡単にインストールできます。
$ brew install direnv
※Homebrew のバージョンが少し古いと、一見インストールがうまくいったように見えて実は足りないコマンドがあったりするので、インストールしてもうまく動かない場合は brew update
をしてからもう一度インストールしてみるとよいかもしれません。
インストールがうまくいったら ~/.bashrc
もしくは ~/.zshrc
に
eval "$(direnv hook bash)" # bash の場合
eval "$(direnv hook zsh)" # zsh の場合
という行を追加してあげれば完了です。
direnv の使い方
spring 入りの Rails プロジェクトのディレクトリ内で
$ direnv edit .
# ※EDITOR環境変数が指定されていない場合はエラーになります。
# 以下のように環境変数を指定してコマンドを実行してもOK。
$ EDITOR=vim direnv edit .
とします。すると EDITOR 環境変数に指定されたエディタが起動しますので、そこに
export PATH=$PWD/bin:$PATH
と入力して保存して終了すると、ディレクトリ内に .envrc
というファイルができます。これで準備完了です。.envrc
があるディレクトリに入ると自動的に Rails の bin/
が PATH に追加されるので
$ rake routes
だけでコマンドが起動します。高速に。
rspec のテストも高速に起動させる
rspec のテストも spring を使って高速に起動させることができます。そのためにはまず gem が必要で Gemfile に spring-commands-rspec
を追加します。
group :development, :test do
gem 'spring'
gem 'spring-commands-rspec'
end
で
$ bundle install
$ spring binstub rspec
こうすることで bin/
ディレクトリ以下に rspec
というファイルができあがります。これで準備完了。テストを起動してみましょう。1 回目はいつもと同じように起動に時間がかかりますが 2 回目以降は起動が早くなっていると思います。
$ rspec spec/
何度も実行するコマンドの実行時間がここまで減ると開発時のストレスはかなり減ります。spring 一度ためしてみてはどうでしょうか。