2011-08-14 15:23:39 +0900
Deviseを使ったRubyアプリのテスト実行を少し高速化する。
Steve Ellis's Blog - NYC Standup 08/12/11: Stretches!に書かれているように、spec_helper.rbに
Devise.setup do |config|
config.stretches = 1
end
という記述を追加して、パスワード暗号化レベルを下げると実行時間が1割ほど減った。
Deviseを使ったRubyアプリのテスト実行を少し高速化する。
Steve Ellis's Blog - NYC Standup 08/12/11: Stretches!に書かれているように、spec_helper.rbに
Devise.setup do |config|
config.stretches = 1
end
という記述を追加して、パスワード暗号化レベルを下げると実行時間が1割ほど減った。
Twitterにも流しましたが、Chromeの同期がちゃんと動作しない人は以下のスレッドの下から2番目のポストを参考に「同期設定のカスタマイズで、パスワードを同期しないようにする」としてみるとよさそう。
Asset Pipelineを備えたRails 3.1のリリースに向けて、その根幹を担うSprocketsをちょっと触っておくことにした。
SprocketsはRubyで書かれたJavaScriptプリプロセッサで、複数のJavaScriptソースファイルを1つにまとめるのが主な機能。それによって以下のようなメリットがある。
今回はRails 3.1には触れないので、Sprocketsを普通にgemとしてインストールする。
$ gem install sprockets
Fetching: sprockets-1.0.2.gem (100%)
Successfully installed sprockets-1.0.2
1 gem installed
インストールが完了するとsprocketizeコマンドが利用できるようになる。
$ sprocketize
Usage: sprocketize [options] filename [filename ...]
-C, --directory=DIRECTORY Change to DIRECTORY before doing anything
-I, --include-dir=DIRECTORY Adds the directory to the Sprockets load path
-a, --asset-root=DIRECTORY Copy provided assets into DIRECTORY
-h, --help Shows this help message
Sprocketsで処理されるJavaScriptでは、requireとprovideという2つのディレクティブを使用することができるほか、YAMLファイルで定義した定数値を埋め込むことができる。
Sprocketsではソースファイル内のコメントを以下のように扱う。
//=で始まるコメントはSprocketsのディレクティブとして扱われる//コメント/** ... **/のようなPDocコメント(PDocはprototype.jsなどで使用されているAPIドキュメント用の記法&ツール)/* ... */コメントrequireディレクティブを使うと、指定したファイルがその位置に展開された状態で結合後のファイルへの書き出しが行われる。指定したファイルが既にrequiredで処理されていた場合は何もしない。
// ロードパス内にあるjquery.jsを読み込む
//= require <jquery>
ファイル名を<...>で指定した場合は、ロードパス内を順にたどってjquery.jsを探し、最初に見つかったファイルが処理対象となる。ファイルが見つからない場合はエラーが発生する。
// 同じディレクトリにあるjquery.jsを読み込む
//= require "jquery"
ファイル名を"..."で指定した場合は、ロードパスの探索は行われず、処理中のファイルと同じディレクトリにあるjquery.jsが探される。
外部のパッケージやライブラリ、プラグインなどを読む場合は<...>を使い、プロジェクト内のソースファイルを読む場合は"..."を使うのが一般的な使い方のようだ。
サブディレクトリ内のソースファイルを読む場合は以下のように指定する。
//= require <foolib/foo>
この場合は、ロードパスの中でfoolibというディレクトリ内にあるfoo.jsというファイルが探される。
CSSや画像、HTMLなどのアセットファイルをJavaScriptプラグインと関連付けるためにはprovideディレクティブを使用する。
JavaScriptファイル内に記述したprovideディレクティブは、現在のJavaScriptファイルがアセットファイルに依存することを示し、JavaScriptファイルに関連するファイル群を一括してドキュメントルートにコピーする機能が利用できるようになる。
例えば、以下のようなディレクトリ構造で、4つの画像ファイル、1つのCSSファイル、2つのJavaScriptファイルを含むcolor_pickerプラグインの場合、
plugins/color_picker/assets/images/color_picker/arrow.png
plugins/color_picker/assets/images/color_picker/circle.png
plugins/color_picker/assets/images/color_picker/hue.png
plugins/color_picker/assets/images/color_picker/saturation_and_brightness.png
plugins/color_picker/assets/stylesheets/color_picker.css
plugins/color_picker/src/color.js
plugins/color_picker/src/color_picker.js
Sprocketsのロードパスにはplugins/color_picker/src/が含まれるようになるという前提で考え、plugins/color_picker/src/color_picker.jsファイルには以下のようなディレクティブを記述する。
//= require "color"
//= provide "../assets"
こうすると、あるアプリケーション内のJavaScriptファイルにrequire <color_picker>という記述があった場合に、Sprocketsによるプラグインの参照が行われ、provideディレクティブによって明示されたアセットファイルがそのアプリケーションのドキュメントルートにコピーされる(ドキュメントルートのimagesおよびstylesheets以下にコピーされる)。
constants.ymlというYAMLファイルで定義した定数を、<%= ... %>という記法で展開することができる。
例えばcolor_pickerプラグインの場合、plugins/color_picker/src/constants.ymlというファイルに以下のような定数の定義を書き、
COLOR_PICKER_VERSION: 1.0.0
COLOR_PICKER_AUTHOR: Sam Stephenson <sam@example.org>
JavaScriptからは<%= ... %>で参照する。
/* Color Picker plugin, version <%= COLOR_PICKER_VERSION %>
* (c) 2009 <%= COLOR_PICKER_AUTHOR %>
* Distributed under the terms of an MIT-style license */
var ColorPicker = {
VERSION: '<%= COLOR_PICKER_VERSION %>',
...
};
定数名はグローバルに扱われ、ロードパス内で参照できるので注意。指定された定数が見つからない場合は、エラーが発生してプリプロセス処理は中断する。
Sprockets本体はRubyライブラリになっていて、それを利用した以下のようなツールが同梱されている。
sprocketize)sprockets-rails)今回は、コマンドラインツールとして呼び出すパターンと、ライブラリとしてRubyのコードから呼び出すパターンを試してみる。
sprocketizeコマンドは引数にソースファイルとオプションを指定すると、ソースファイルを結合したものを出力するので、それをファイルにリダイレクトして保存します。
コマンドラインオプション。
-C, --directory=DIRECTORY 処理前にディレクトリを移動する
-I, --include-dir=DIRECTORY ロードパスにディレクトリを追加する
-a, --asset-root=DIRECTORY アセットをディレクトリにコピーする
-h, --help ヘルプメッセージを表示する
-v, --version バージョンを表示する
使用例。
$ sprocketize -I app/javascripts \
-I vendor/sprockets/prototype/src \
-I vendor/sprockets/color_picker/src \
--asset-root=public \
app/javascripts/*.js > public/sprockets.js
上記のコマンドでは、app/javascripts/*.jsが1つにまとめてpublic/sprockets.jsとして保存される。その際、
app/javascriptsvendor/sprockets/prototype/srcvendor/sprockets/color_picker/srcの3つのディレクトリがロードパスに追加され、requireディレクティブで参照されるファイルの探索が行われる。また、requireで読み込んだファイル中にprovideディレクティブが記述されていた場合は、その値に応じたアセットファイルがpublic以下にコピーされる。
RubyのコードからSprocketsを使用する場合は、以下のようにSprockets::SecretaryクラスとSprockets::Concatenationクラスを利用する。
# オプションを指定してSprockets::Secretaryオブジェクトを生成する
secretary = Sprockets::Secretary.new(
:asset_root => "public",
:load_path => ["vendor/sprockets/*/src", "vendor/plugins/*/javascripts"],
:source_files => ["app/javascripts/application.js", "app/javascripts/**/*.js"]
)
# ソースファイルの結合を行うSprockets::Concatenationオブジェクトを生成する
concatenation = secretary.concatenation
# 結合結果をファイルに保存する
concatenation.save_to("public/sprockets.js")
# アセットファイルをコピーする
secretary.install_assets
Sprockets::Secretary.newには以下のようなオプションが指定できる。
:root
.):asset_root
:load_path
:rootからの相対指定となる):source_files
:rootからの相対指定となる):expand_paths
load_pathおよびsource_filesに含まれるパスをシェルのグロブルールで展開するかどうかをtrueかfalseで指定する:load_path => ["vendor/sprockets/*/src"]などが展開されるかどうかtrueSprockets自体はprototype.jsなどのパッケージングでも利用されており、RubyやRailsとは無関係のプロジェクトでも重宝しそう。Rails 3.1での利用が前提ならば、実行環境はおいといてとりあえずディレクティブの働きだけを理解すればよさそう。
heroku.gemが2.4.0にアップデートした。
SSL周りの変更がほとんどみたいで、ユーザーに直接関係しそうな変更はSKIP_PLUGINS環境変数で任意のプラグインのロードをスキップできるようになったことくらいかな。
HerokuのAPIを叩くのにはユーザー名とパスワードを送る必要があると思っていたのですが、いつの間にかHerokuのMy AccountページにAPIキーが表示されるようになっていて、herokuコマンドもAPIキーを利用する形になっていたようです(知らなかった)。
自分のマシンの~/.heroku/credentialsには今もユーザー名とパスワードがベタに格納されている状態だったので、いったんcredentialsを削除してからherokuコマンドを呼んでユーザー名とパスワードを入力したところ、credentialsにはユーザー名とAPIキーが格納されるようになりました。
$ rm ~/.heroku/credentials
$ heroku list