RubyGems 1.1.0 released
RSpecに関する記事の自分用まとめ
RSpecはTest::Unitの代わりに使えるテストフレームワーク。テストが普通の言語風に書けるのが特徴。Railsプラグインが用意されており、script/generate時にmodelやcontrollerの代わりにmodel _spec、controller_specを使うことでRSpecのテスト環境を自動生成することができる。ControllerをModelから分離した形でテストできたりするのが良い感じなので、こちらの仕様を検討してあちこちのサイトを見て回っている。中でも、るびまに連載中の「スはスペックのス」が非常によい記事なのだが、ちょうどるびま23号が出たのでそれ以外の見ているページを含めて自分用にまとめてみた。
- RSpec1.1.3 Overview
- RSpecの本家。英語だがチュートリアルも色々ある。
- スはスペックのス 【第 1 回】(るびま)
- スはスペックのス 【第 2 回】(るびま)
- とりあえず読んでおくべき記事。第1回がmodel、第2回がcontrollerとview。
- RSpec参考サイトまとめ(ひげろぐ)
- ここからリンクをたどれば重要な記事にはたどり着けると思う。
- Mocks Aren't Stubs
- Ruby on Rails でのモックとスタブの作成(developerWorks Japan@IBM)
- RSpecでモックとスタブ(ひげろぐ)
- Rspecでコントローラのspecファイルを書く(kaeruspoon)
- Ruby on Rails でのモックとスタブの作成(developerWorks Japan@IBM)
- モックとスタブがよくわかんないので色々彷徨っている。
- RSpecに待ちに待ったIntegration TestのRBehaveが追加(InfoQ)
- 統合テストの作成はまだ先だけども一応。
Specimenはspecimanの複数形じゃないって
Railsでは名詞の単数形と複数形は厳密に使い分けなければならないことがある。たとえばsequenceのモデルとなるクラスはSequenceで、データベースのテーブル名はsequencesだ。不規則変化の名詞もあるので、単数形と複数形を変換するためのメソッドがActiveSupportのInflectorモジュールで定義されている。複数形にするstring#pluralizeと単数形にするstring#singularizeだ。さらに、モデルとなるクラス名は大文字から始まる単数形(正確にはそれをcamelizeしたもの)なので、それを求めるためのstring#classifyメソッドもある。つまりこんな感じ:
"sequence".pluralize = "sequences" "sequences".singularize = "sequences" "sequence".classify = "Sequence"
舞波本で紹介されているar_fixtureプラグインを利用してfixtureを作成するdb:fixtures:saveというrakeタスクを利用して自分のデータベースを変換しようとしたら、失敗してエラーメッセージに"speciman"なる奇妙な単語が。どうやら、rakeタスク中のclassifyメソッドによってspecimenをspecimanの複数形だと思われて勝手に変換されてしまったらしい。早速実験。
"sequences".singularize = "sequences" "sequence".singularize = "sequence" "specimens".classify = "Specimen" "specimen".classify = "Speciman" "specimen".singularize = "speciman"
oops. 要するに、classifyってsingularizeしてcamelizeしてるだけなので、問題になっているのはsingularize。普通は単数形をsingularizeした時は、同じ単数形が返るのだが、specimenは語尾がmanの複数形になっていることが影響してspecimanになってしまう。railsの単数形ー複数形の変換機構が同じ語尾を持つ不規則名詞を自動的に変換するのだが、それが仇になったようだ。
こういうときのためにInflectorには、新しい不規則名詞を教えるための設定方法がある。Railsアジャイル本ではgooseーgeeseを教え込ませていた(そのままだとgoose-goosesとなる)。そこでenvironment.rbに書き加えてみる。
Inflector.inflections do |inflect| inflect.irregular "specimen", "specimens" inflect.irregular "goose", "geese" end
なお、この項はrunブロックの外側に書くこと。でないとuninitialized constant Inflectorなるエラーが出る。そして再度実験。
"goose".pluralize = "geese" "geese".singularize = "goose" "specimen".singularize = "speciman"
oops. で、singularizeのソースを見てみると、
def singularize(word)
result = word.to_s.dup
if inflections.uncountables.include?(result.downcase)
result
else
inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
result
end
end
となっていて、単数化のルールはInflector::inflections.singularsにある。これを見てみると、
[/(g)eese$/i, "\\1oose"], [/(s)pecimens$/i, "\\1pecimen"] ... [(m)en$/i, "\\1an"] ...
という順番で評価されるのだから、specimenを無理矢理singularizeすれば、先ほど定義したspecimens→specimenというルールは無視され、そのあとにあるmen→manが使われるのは自明の理。つまりclassifyメソッドを改良するなりなんなりしないと話にならんと言うことか。とりあえず応急処置するとしても、何だかなあ。
Rails1.2.6 + Ruby-GetText-Package1.90.0 でrhtml処理時にエラー?
Ruby-GetText-PackageはRailsで使えるGNU GetText(Wikipedia)のようなライブラリで、データベースの多国語対応を効率化してくれる。簡単に言えば、ウェブサイトで訳すべき箇所に印を入れておくと、それを集計したセンテンス集を作ってくれて、あとはそれを誰かが訳せば、各国語版になるわけだ。GBIFやDNAバーコーディングのデータベースでも、ミーティングでは各国語へどう対応するのかが大きな問題になっている中、そこを簡単にクリアできてしまう。
ただ、ちょっと問題が。ちょっと新しいサーバでRails1.2ベースのデータベースを動かしてみようと思い。gemで最新のGetText1.90.0を入れて試してみたら、なぜかrhtmlファイルが処理されなかった。削除して一つ前のバージョンに戻したら他に修正なし(辞書ファイルもそのまま)でちゃんと動いたので、単純に仕様の問題だと思う。1.90.0はRails2.0対応版だから、rhtmlやめてhtml.erbにしろってことなのかな。
データベース構造をリセットするmigration
db:migrate VERSION=0 db:migrateとやる必要があったが、Rails2.0では
db:migrate:resetでいけるらしい。これは便利かも。
Railsプロジェクトを操作するrubyスクリプトの実行
ruby script/runner "load('foo.rb')"
とすればいい。ただしevalな実行環境なので遅い。
Migrationでfixture dataをセットする
class CreateFixture < ActiveRecord::Migration def self.up gaist = User.create(:name=>"gaist", ...) data = Data.create(:user=>gaist , ...) ... end def self.down User.delete_all Data.delete_all end
script/generateで単独のMigrationクラスを作成する
ruby script/generate migration add_user_columnでAddUserColumnクラスの入ったxxx_add_user_column.rbが作成される。
ヌルないし空かどうかを調べるスマートな方法
表形式のテキストを読み込んでsplitで配列に分割すると、表の末尾の空白セルはnilになってしまう。そのため、空文字列かどうかを判別するためにif s.empty?と書くとエラーになってしまうため、
s.nil? || s.empty? s.to_s.empty?
などと書かないといけない。
RailsのActiveSupportには色々な小粒な山椒のようなメソッドがあるが、この問題の場合は、やはりActibeSupportで追加されるメソッドblank?が使える。これを使うと、s.blank?
と書ける。Rails使わなくてもややこしいテキスト処理をしたいときについついrequireしたくなるメソッドの一つ。
(c) Utsugi JINBO/Gaist 2001-2007















