トップ 最新 追記

2010-12-05 [長年日記]

_ 最近のJavaScriptのテスティングフレームワークについて調べてみた

あるいは kanazawa.js v0.0.1 勉強会 : ATND に参加してきた。

今回はとりあえず今注目している JavaScript テスティングフレームワークの紹介というかリンク集めだけ。

まとめ

  • QUnit と Jasmine について調べたよ!
  • 好きに使って! Jasmine の使い方はまだ書くことあるんだけど疲れたからまた今度ね!

書いたよ! Jasmineをもう少し詳しく紹介してみる も読んでみて!

自分の背景

JsUnit を使って中規模なコードを書いた経験がある。普段は PHP + SimpleTest で概ね TDD で書いている。Ruby はまだ Test::Unit を使っている。RSpec に移行したいと思いながらタイミングをつかみそこねている。

テスティングフレームワークにできること

  • まず原則は JS のみのユニットテスト

これをユニットテストと呼ぶか TDD と呼ぶか BDD と呼ぶかは背景の文化によるが、少なくともできることにものすごく大きな差があるわけではないと考えておいて間違いない。

DOM を操作するものについては JS コードを呼び出す HTML に対して操作を加え、結果をテストするのが基本になる。(はず。)

またサーバサイドの動作とは基本的に切り離して考えておく。サーバが静的な HTML しか返さないならそれをテストコードに与えればよいし、Ajax 対応は今まさにテスティングフレームワークがしのぎを削って対応を進めようとしている課題のようだ。もう少し待て。

今回の2つに共通すること
  • 古い xUnit 系よりも自由に名前付けできる

xUnit 系の率直な実装は基本的にテスト名はメソッド名になってしまう。したがってテストの意図を記述しにくいことがある。今回紹介する2つにはそういう制限はない。

QUnit

jquery/qunit - GitHub

個人的な印象は schwern/test-more - GitHub というか Blog | New testing framework | symfony | Web PHP Framework のような感じ。要するに比較的シンプルにテストを書けるもの。

というより恐らくいちばんウケているのは

準備が楽

ってことだと思う。基本的には qunit.js と qunit.css とそれを読み込む HTML さえあればテストを書くことができる。

基本的な使い方

最も基本的な使い方は以下のような HTML を用意してブラウザで読み込む。

これは http://docs.jquery.com/QUnit にあるデモから jQuery 依存の部分を除いたもの。やってみれば分かるけど普通に jQuery 無関係に動く。*1

参考

【レポート】jQueryテストスイート「QUnit」がスタンドアロン化! 使い方を早速チェック (1) QUnitとは? | エンタープライズ | マイコミジャーナル

Jasmine

個人的にはこっちが本命。明確に RSpec-inspired.

Jasmine: BDD for Javascript | Jasmine

Pivotal Labs がメンテナンスをしている。実はこれすごく重要。なぜなら JsUnitpivotal/js-spec-server - GitHub も関係している Pivotal Labs があえて新しい JavaScript Testing Framework を作っているのだ。これが良くなくて一体何が良いのだ。

また、relevance/blue-ridge - GitHub というかなり気合いの入った Framework も今は「もうやらないから Jasmine 使え」って言ってるくらいなんだから、本命中の本命と言っていいと思う。

Pivotal Labs の名前を意識するようになったのはE和さんの中で流行っているという話を聞いてからだけど、jsUnit 自体は以前から知っていたので、これは正直期待しちゃうってもんだ。

related projects などはまだアッチッチかもしれない。でもこれは結構期待できそう。

Jasmine で fixture

velesin/jasmine-jquery - GitHub

を使うと割と素直に目的を達成できる。jasmine-jquery という名前だが別に jquery を使う必要はない。

同じような目的で jeffwatkins/jasmine-dom - GitHub というものもあるのだが、どうも fixture 周りの動きが変。コード自体はものすごく酷似してるんだけど、なんか変。

Jasmine で Ajax

pivotal/jasmine-ajax - GitHub

というプロジェクトがあるんだけど、まだあまり日本語で話を聞かない。今やったら日本人の中ではリードできるかも。

headless

headless っていうのは GUI-less のことだと思ってるんだけど、この取り組みはいくつかある。

  1. jeremylightsmith/class.TDD-in-javascript-with-headless-jasmine - GitHub
  2. injest - Project Hosting on Google Code

これもまだあまり話を聞かない。

参考

*1 ただしコードを追うと中にはまだ jQuery を呼び出している部分があるので完全に jQuery がなくてもよいわけではないっぽい。


2010-12-06 [長年日記]

_ いい仕事したいじゃん

改めて思った 2 + 1 のこと

最近、人に話すことで改めて自分の思いに気づいたことが二つある。

  • いい仕事をしたい
  • 中小企業には時間も人手も余裕はない

軽く掘り下げて書き残しておきたい。そして書いている途中で出てきたのが

  • 老害になりたくない

である。これも残しておこう。いつか振り返ったときにいろいろ思えるかもしれない。

いい仕事したいじゃん

「いい仕事」という言葉はいろいろな意味を含む。人によって定義が変わってしまう曖昧な言葉とも言えるけど、ここではとりあえず曖昧なまま行ってしまっていいんじゃないかと感じている。エンジニアにはエンジニアの、営業には営業の、会計には会計のいい仕事があるはずだ。それでいいと思う。

正直なところ自分は何もしなくていいなら何もしたくない人間だ。好きなことだけダラダラできるならこんな素晴らしいことはないと思うし、それでも恐らくヒマで困っちゃうようなタイプではないと思っている。

ところが残念ながら現実はそう甘くない。仕事しないと生きていけない。社会が抱えるあまりに大きな負債について「なんでこんなアホな話ばっかなんだ」と思うことは多いけれど、ひとまずそれを置いて目の前の問題に対処しなければいけない。つまり仕事するのだ。

どうせやり続けなくちゃいけないのならば「いい仕事」をしたいと自分は思うタイプである。アジャイル的には「お客様の満足」と言うのがここはかっこいいところなんだけど、あまり一つの言葉で置き換えてしまいたくはない。将来の自分が開発しているとも限らない。

中小企業には時間も人手も余裕はない

これは大きな会社でも特に真面目に国内トップレベル、あるいは世界レベルで「競争」しているところも同じかもしれない。要するに

余っているものなんか何もない

のだ。だから「本当に必要なの?」と疑問に感じるような仕事はどんどん見直さなくちゃいけない。

例えば IT の世界でよく聞くのは

  • のちにちゃんと振り返りもしないのに大量に書かされる言い訳文書
  • メンテナンス性、検索性の悪い Excel 仕様書
  • 重すぎてまともに作業できない Excel のバグ票
  • 仕様書と合ってないコード
  • 酷似しているのに微妙に違う大量のコピペコード
  • 意図を伝えず動作だけを説明する「意味のない大量のコメント」
  • 作業効率を著しく落とす「コメントアウトされた前バージョン」

これらはすべて現実によくある話*1。ここで挙げたのは大まかに

  • 無駄な文書、無駄なコード
  • 作業効率の悪い文書フォーマット、作業効率の悪いコード(読みにくいコード)

に集約される。

つまり日々の生産性を確実に落とすものたちだ。ということは全部見直しの対象である。見直さないと、本来達成すべき「価値」ではなく「作業」に自分の「手」と「意識」を奪われてしまう。

しかしここで問題になるのが多層下請け構造。元請けなら文書、コードのルールは自由に設定できるが、下請けの場合はそうもいかないこともよくある。幸い自分はそういう環境にはないので、直せるところは直していかないと

競争力を失って退場させられてしまう。

それが我々の生きる世界なのだ。

老害にはなりたくない

あれ、三つ目がでてきてしまった。

書いてるうちに再確認できたことがもう一つあった。自分は

老害にはなりたくない

んだなと強く思った。

上に挙げた問題は基本的に

過去を踏襲しているだけの作業が新たな価値の創造を阻害している

と言えると思う。つまりかつてはそれが最善と思われたのでそうなったのだ。多少好意的解釈を多めに加える必要はあるが。しかし今はより適切な道具を適切に使いさえすればもっと良い作業に変えることができる。少なくとも

  1. 現代的なバージョン管理システム
  2. 現代的な Issue Tracking System

を正しく運用すれば、上の問題の多くは解消できる。もちろん導入しただけですべて解決するわけではない*2が、少なくともルーチンワークのコストを下げる準備はできる

だからこの二つは最低限達成しなければいけない。

しかしそこで浮上してくるのが

教育/学習コスト

の問題である。

ここは残念ながら失うものの多いベテランの抵抗が強い。年を取れば取るほど新しいものの習得は億劫になるし、ヨーイドンで同時に学習を始めたら若いやつにかなう訳がない。気持ちは分からなくはないが、もうその状態は老害になっていると思った方がいい。

自分を振り返って、自分の周りの人間を観察して思い当たることはないだろうか。はっきり言って自分で触ってもいないのにしたり顔で○○の批評をするやつは老害だ。年齢は関係ない。気をつけて掛からなきゃいけない。○○には何を入れてもいい。ちょっと前ならスマートフォンが入るし、とりあえず新しめのものを入れればだいたい成り立つ。

自分は今ちょうど境目にいると思っている。今はまだ老害ではないが、ちょっと学ぶ意欲が足りなくなったらあっという間に老害になる危険を感じている。学ぶ意欲というのは個性かもしれないが環境の問題もやはり大きい。老害になった方がいいかもしれないと感じてしまうようなら、「見捨てる」結果になるとしても、環境を変えた方がいいのかもしれないとも思う。

あるいは例えば新しい技術についての判断はしない、ただの老として生きるか。今の自分はまだ老害に腹を立てる側の人間である。つもりだ。しかしいつか労害になり得る。いつかストップを掛けてしまう側の人間になる。そのときにはもうその判断をしない立場にならなければいけないのではないかとも思っている。

*1 プロダクトオーナーの意思と合ってない仕様書はまた別な話。

*2 少なくともバージョン管理するだけではクソコードは良くならない。バージョン管理したうえで無駄をどんどん削ぎ落としていく作業は必要である。


2010-12-07 [長年日記]

_ Jasmineをもう少し詳しく紹介してみる

Jasmine: BDD for Javascript | Jasmine

先日プッシュした Jasmine についてもう少し掘り下げていきます。ただしテストの書き方については触れません。それは公式の情報やすでに詳しく紹介されている記事があります。

まとめ

  • Jasmine は見た目だけでなく考え方も RSpec の影響を受けているよ
  • 多少遠回りでも rubygems 版の Jasmine を使うとテストが本当に自動化できるよ

わざわざツールを使ってテストしたいということはある程度アプリケーションとして規模が大きいとか、サイトとして規模が大きく JavaScript の数が多くなっているので、人力チェックが大変だということではないでしょうか。

規模が大きくなってきた場合は、ある程度作法(ルール)を用意してそれを守ることが安全、安心なアプリケーションの開発、作成に欠かせません。Jasmine は単に JavaScript で JavaScript のテストコードが書けるだけではありません。より良い配置、より良い命名を促します。

特徴

見た目的にも明らかに RSpec の影響を受けていますが、構造的にもいわゆるヘルパー付きテスティングフレームワークの考え方を取り入れています。具体的に何が起きるかというと、

プロダクトコードもテストコードもいっぺんに読み込もうとします。

疑問点

上の特徴を踏まえると以下のような疑問が湧いてきます。

  • 1. HTML の中の JavaScript はどうやってテストするの?
  • 2. jQuery のチュートリアルなどによくある
$(document).ready( function() {
   ...
});

のようなコードはどうやってテストするの?

  • 3. 複数の JavaScript をいっぺんに読み込んだら他のコードに影響出たりしないの?

たぶんこれが回答

  • 1 については、テストしたいコードは HTML から分離しましょう
  • 2 と 3 はちゃんとオブジェクトに名前を付けてぶつからないようにしましょう

実はこれはもう

日本RubyKaigi2010 3日目 - まちゅダイアリー(2010-08-29)

を読めば想像がつきます。

ちょっとした効果にしか使わない場合は面倒に感じるかもしれませんが、コードをコードでテストする TDD や BDD は、やってないときに比べるとスタート時点では多かれ少なかれ面倒なものです。ここはそういうものと割り切ってください。あとでまた補足します。

使い方

二つあります。

  • standalone
  • rubygems + rake
standalone

以下に jasmine-standalone-1.0.1.zip の内容を挙げます。

├── SpecRunner.html
├── lib
│   └── jasmine-1.0.1
│       ├── MIT.LICENSE
│       ├── jasmine-html.js
│       ├── jasmine.css
│       └── jasmine.js
├── spec                <-- specファイル(テストコード)置き場
│   ├── PlayerSpec.js
│   └── SpecHelper.js
└── src                 <-- プロダクトコード置き場
    ├── Player.js
    └── Song.js

上の src/ にテストしたい JavaScript コードを、spec/ 以下に spec ファイル(テストコード)を置きます。spec ファイルの名前は

「元の名前 + [Ss]pec」.js

が推奨されています。実際には standalone の場合は自由ですが、gem 版を使うときにはこのルールがデフォルトなので、合わせておいた方がいいと思います。

そして各ファイルのパスを SpecRunner.html の中に書き、このファイルをブラウザで開くことですべてのテストが自動的に実行されます。

付属しているサンプル SpecRunner.html は以下のようになっています。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title>Jasmine Test Runner</title>
  <link rel="stylesheet" type="text/css" href="lib/jasmine-1.0.1/jasmine.css">
  <script type="text/javascript" src="lib/jasmine-1.0.1/jasmine.js"></script>
  <script type="text/javascript" src="lib/jasmine-1.0.1/jasmine-html.js"></script>

  <!-- include source files here... -->
  <script type="text/javascript" src="src/Player.js"></script>
  <script type="text/javascript" src="src/Song.js"></script>

  <!-- include spec files here... -->
  <script type="text/javascript" src="spec/SpecHelper.js"></script>
  <script type="text/javascript" src="spec/PlayerSpec.js"></script>

</head>
<body>

<script type="text/javascript">
  jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
  jasmine.getEnv().execute();
</script>

</body>
</html>

ここまでは見れば分かる通りです。QUnit と違ってサンプルの段階でテストを HTML の中に書くのではなく、テストを記述した spec ファイルとして分離することが推奨されています。

standalone 版はテストするコードが増えればこの HTML の編集の手間も増えていきます。

rubygems + rake

プロダクトコードとテストコードの配置については standalone 版と同じですが、SpecRunner.html の編集は必要ありません。ただし、当然

  • ruby
  • rubygems

が必要です。

面倒ですか? でもこれが用意できれば画期的に楽に安心を手に入れることができるようになります。もう少し続けましょう。

rubygems版Jasmine

インストール
gem install jasmine

で入ります。(Windows では試したことがないですが。)selenium など他にも依存しているライブラリがインストールされるので多少時間が掛かると思います。

いちばん基本的な使い方

Rails2, Rails3, その他用の使い方の説明が Using the Jasmine Gem | Jasmine に書かれていますが、ここでは最も何も考える必要のないその他用をもとに説明します。なお、Ruby と Rubygems はインストール済みとします。

すると jasmine のインストールから使い始めはこんな感じになります。

$ gem install jasmine
$ mkdir jasmine_test
$ cd jasmine_test
$ jasmine init
$ rake jasmine

これだけです。すると以下のように WEBRick サーバが立ち上がります。

(in /path/to/jasmine_test)
your tests are here:
  http://localhost:8888/
[2010-12-08 18:35:04] INFO  WEBrick 1.3.1
[2010-12-08 18:35:04] INFO  ruby 1.8.7 (2010-08-16) [i686-darwin9]
[2010-12-08 18:35:04] INFO  WEBrick::HTTPServer#start: pid=56941 port=8888

サンプルのSpecRunner.htmlを開いてJasmineを実行したところ

ここで http://localhost:8888/ にアクセスするとテストが実行されて右のように結果が返ってきます。

jasmine init したディレクトリの構成

このとき jasmine init を実行したディレクトリの中身は以下のようになっています。

├── Rakefile
├── public
│   └── javascripts
│       ├── Player.js
│       └── Song.js
└── spec
    └── javascripts
        ├── PlayerSpec.js
        ├── helpers
        │   └── SpecHelper.js
        └── support
            ├── jasmine.yml
            └── jasmine_runner.rb

あれ、SpecRunner.html がありません(わざとらしい)。実は ./spec/javascripts/support/jasmine.yml に秘密があります。コメントを省いて内容を掲載すると以下になります。

src_files:
    - public/javascripts/**/*.js
stylesheets:
helpers:
spec_files:
src_dir:
spec_dir:

ここで各種ファイルの位置と名前を指定します。基本的にデフォルトのままで大丈夫です。自動的に各種ファイルを拾い上げてそれを <script> で読み込むように作られた HTML がサーバから送られてくるので、テスト対象の JavaScript が増えても上のルールにマッチする限りは何もする必要がありません。

デフォルトと異なる場所に JavaScript を置きたい場合は jasmine.yml を書き換えてください。

jasmine gem の中身
├── MIT.LICENSE
├── README.markdown
├── bin
├── generators
├── jasmine
├── lib
│   ├── jasmine
│   │   ├── ...
│   │   ├── run.html.erb   <-- コレ
│   │   └── ...
│   └── jasmine.rb
└── spec

この中の run.html.erb がキモです。

http://localhost:8888/ にアクセスすると先ほどの YAML の中身が自動的にこの中に展開されたものがブラウザに返されます。

したがっていちいち SpecRunner.html を編集せずに、js ファイルを所定の場所に置くだけで自動的にすべて読み込むことが可能になるわけです。

rake jasmine:ci がすごい

gem 版の Jasmine では基本的には

rake jasmine

を実行して http://localhost:8888/ にアクセスしてテストするのですが、これを全自動にするのが

rake jasmine:ci

です。これは *1selenium を利用してブラウザ(デフォルトは Firefox)を操作してテストの結果を得ます。つまり上のコマンドを叩いたあとはただ待つだけです。

(in /path/to/jasmine_test)
/opt/local/bin/ruby -S rspec --color --format progress "spec/javascripts/support/jasmine_runner.rb"
Waiting for jasmine server on 56662...
[2010-12-08 18:41:30] INFO  WEBrick 1.3.1
[2010-12-08 18:41:30] INFO  ruby 1.8.7 (2010-08-16) [i686-darwin9]
[2010-12-08 18:41:30] INFO  WEBrick::HTTPServer#start: pid=57246 port=56662
Waiting for jasmine server on 56662...
jasmine server started.
Running: java -jar "/opt/local/lib/ruby/gems/1.8/gems/selenium-rc-2.2.4/vendor/selenium-server.jar" -port 56670 > /dev/null
==> Waiting for Selenium RC server on port 56670... Ready!
Waiting for suite to finish in browser ...
.....

Finished in 0.18192 seconds
5 examples, 0 failures

こんな結果が返ってきます。(MacPorts で入れた Ruby で実行。)

ブラウザがすでに起きていても新たに起動するところから始めるので動作は遅いのですが、全自動で実行できるのは魅力です。これを CI サーバで実行するようにしておけばいつも JavaScript のコードが正しく動いているかテスト済みの状態を維持できるようになるわけです。

こうなるととても安心です。各種ライブラリのバージョンを上げたときの検証など、大幅に省力化できるのではないでしょうか。

参考

*1 今のところ


2010-12-11 [長年日記]

_ 今さら始めるRails 3

Ruby との付き合いはそれなりに長いのですが実は Rails で何かを作ったことは一度もありません。*1scaffold や migration は一通り試してみたことがあったけれども、何か拭えない不安感や縁のなさから今までは周辺技術の一つとして以上には触ったことがありませんでした。

興味

今回、出遅れはしたけれども

  • 全面的に Merb & Rack ベース
  • Arel 登場
  • i18n の機構が組み込み済み
  • すでに実績が増えてきている

辺りで強く興味が湧いてきたのでまずは一通りの準備をしてみました。

消極的な理由

消極的な理由も実はあって、それは

  • PHP のレガシーコードと戦うのに疲れた
  • 負債のある PHP で最新バージョンに追いつくのは大変
  • 最新バージョンでないと PHP や PHP のフレームワークの旨味は味わえない
  • Ruby なら最新でなくたって遊べる
  • Rails の過去の作法をほとんど知らないので混乱しない

他のどんな言語でも似たようなものだとは思いますが、レガシーコードを大量に抱えてしまうとアップグレードできずにキャッチアップが難しくなります。また rvm のような仕組みもない PHP では最新の情報を手元でだけ試しておくという準備もしにくいです。その点 Ruby には rvm もあるし gem は複数バージョンを保持できるし、良いテストの文化があります。

まずはインストール

の、前に Ruby は 1.8.7 以上が必要です。Windows なら installer で入れればいいです。rvm をすでに使っているなら好きなものを入れてください。困るのは RHEL 5 系 Linux でバイナリインストールしかしない人で、その場合は

End Point Package Repository

を使ってください。RHEL 6 な人は Rails 3 ready らしいです。

あとやることは

$ gem install rails

だけ。依存ライブラリはどかどか入りますので、しばらく待ちます。あとは必要に応じて

  • sqlite3-ruby
  • rails-erd
  • jpmobile
  • rspec-rails
  • typus
  • jasmine
  • cucumber-rails

など、お好みで。Cucumber はまだズルズルきております。いい加減やらないと。

RSpec は 2 以上が Rails 3 対応です。現時点(2010-12-11)では何も考えずに最新を入れれば大丈夫です。本当に Rails 3 のリリースにみんなが足並みを揃えたことがよく分かります。ありがとう。

アプリケーションの雛形準備

rails new foo でアプリの雛形を作成します。

$ rails new foo -T -J

このとき -T -J でそれぞれ Test::Unit と prototype.js 依存を取り除けます。が、ここではまだ取り除けるだけ。

Gemfile の編集

Rails 3 からは Bundler の仕組みを使って依存 gem を管理します。どういうことかというと

  1. 使いたい gem を Gemfile に列挙
  2. Gemfile を編集したら bundle install

が、おまじないとして増えたということです。

これはもしかしたら面倒に感じる人が多いかもしれませんが、サーバ管理する人間からすると、どのアプリで何のライブラリを使ってるのかよく分からない状況になりがちで「もう全部 rsync すればいんじゃね」くらいしか打つ手のなかった最近の状況に対するとてもスマートな回答として、個人的には嬉しく思っています。大規模なサイトしか相手にしない場合はライブラリ管理は「そのサイトで必要なもの全部」なのでそこまで面倒じゃないのですが、小さいものをいくつも VirtualHost で収めているような場合は困ります。

ここでは以下のようにしてとりあえずどかどかインストールしてみます。

gem 'jpmobile'
# gem 'jquery_rails3' # NOT WORK !!
gem 'jquery-rails'

group :development, :test do
  gem 'rails-erd'
  gem 'rspec-rails'
  gem 'jasmine'
  gem 'typus'
end

こんな感じ。

では以下に各 gem の使い方などを簡単に紹介していきます。

rails-erd

Rails ERD &#8211; Entity-Relationship Diagrams for Rails

これは面白いです。Rails 3 用というか正確には ActiveRecord 3 用で、

生成済みの Model の情報から ER 図をそれっぽく起こします。

graphviz に依存していますし、graphviz のバージョンによってはきれいな図が描けないので注意が必要です。すべて適切に動いていれば

rake erd

で ERD.pdf が作成されます。これで Rails の環境から離れてマウスをポチポチやることなく ER 図が作れます。嬉しい。それに最近の ORM を使った開発では DBMS を抽象化しているので DBMS を schema dump しても正しい関係を抽出できないんですよね。リレーションも DBMS ではなく Model 間で考える必要がある*2ので、こういうツールがとても嬉しいです。

※ 試した範囲では以下のような感じで動いたり動かなかったりしました。

バージョン プラットフォーム 結果
2.26 MacPorts OK
2.22 CentOS 5 NG
(失念) Fink NG
2.20 Debian OK

単に新しい方がよい、ってわけでもないみたいです。

RSpec

RSpec - Relish

bundle install に成功していれば rails g コマンドに rspec:install が現れる*3ので、これを使って spec の雛形を用意します。

$ rails g rspec:install

まだ実際に spec を書いたことはないので、以下略。

jQuery

[2010-12-27 修正]

indirect/jquery-rails - GitHub

Rails 標準は prototype.js なのですが、これは先ほどの rails new で抑止してあるので、改めて jQuery を入れます。rspec と同様に rails g コマンドに jquery:install ができます。

$ rails g jquery:install

最初間違ってしまったのですが、jquery_rails3 はダメで、jquery-rails だとうまくインストールできます。

もしすでに prototype.js 依存で project を new してしまっていてもちゃんと取り除いてくれます。

なんかエラー出ますね。git の最新 jquery を取得する処理でコケてるっぽいです。https 周りかな。

放置します。

今回はとりあえずカッコがつけばいいので。

jpmobile

jpmobile - A Rails plugin for Japanese mobile-phones

すんなり使えます。ただし実際に機能させるには config をいじらないとダメです。Rails の config はこの辺にあります。

RAILS_ROOT/config/
├── application.rb
...
├── environment.rb
...

今回は environment.rb を以下のようにいじってみました。どこをいじるのが正解なのかは分かりませんが。

# Load the rails application
require File.expand_path('../application', __FILE__)

module Demo
  class Application
    # jpmobile
    config.jpmobile.mobile_filter
  end
end

# Initialize the rails application
Demo::Application.initialize!

これだけで端末に応じた view の振り分けはすぐに使えます。キャリアに応じて文字コードの変換も自動でやってくれるし、スマートフォン対応も簡単にできそうです。これは便利。

※ 今回 Rails 3 に関心を持っているもう一つの理由がこの jpmobile です。PHP でモバイル対応しようとしてもこれだけの完成度のものは公開されていないと思います。

Bundler

Bundler: The best way to manage Ruby applications

bundle install はすでに使っていますが、

$ bundle install [PATH]

あるいは

$ bundle install --deployment

を実行すると RAILS_ROOT/.bundle/config が作成され、この中にパスの情報が残るようです。この情報が残っている限りは単に

$ bundle install

を実行しても system の gem のパスではなく、プロジェクト独自のパスに入るようになります。なるほどなぁ。

Typusで管理画面は横着する

Typus Core: Admin Panel for Ruby on Rails Applications

DBMS を使うアプリで面倒なのはやはり管理画面じゃないですかね。管理画面がないとずっとお守りをしなければいけなくなるけど、表に見えるわけじゃないのでつい億劫になりがちです。

そこで管理画面の作成を助けてくれるものは必要だろうと以前から思っていたのですが、とりあえず Typus は現状でも Rails 3 で使えそうです。

$ rails g model

...

$ rake db:migrate
$ rails g typus

すると、作成済みのモデルの情報からそれなりの管理画面が自動で生成されます。

ただし、model の変更には恐らく追随できないので、ある程度構造が固まってから generate した方がいいかもしれません。

ruby-toolbox.com の Rails Admin Interfaces で2番人気、Rails 3 対応のものでは1番人気なので、外れではないんじゃないでしょうか。

※ 実は Typus を試す前に Casein - A lightweight Ruby on Rails CMS を試していたのですが、jpmobile とぶつかってにっちもさっちもいかなくなっていたのでやめました。見た目的には Casein の方がかっこよさそうなんですけどね。

Jasmine

Jasmine: BDD for Javascript | Jasmine

これは以前の紹介と違って

$ bundle exec jasmine init

するだけです。あとは一緒。

Arel

$ rails console

の中でちょっと試してみました。

Model.select( 'foo, bar' ).where( 'bar != baz' ).limit( 2 )

みたいに書いていきなり結果が取得できます。うっは。おまけに

.to_sql

を付ければ発行される SQL がすぐに確認できます。

なんじゃこりゃ!

ORM への抵抗が一気になくなりますよ、これ。ステキすぎます。

i18n

※ できることとできないことが分かりました。

RAILS_ROOT/config/locales/

以下に .rb な Hash か .yml な YAML でメッセージカタログを用意するのが標準の方法みたいです。

ここでいじったものはちゃんと locale の設定ができていれば Typus で自動生成した管理画面にも反映されます。ちょっと感動。*4

ただし Typus が model 名ではなくテーブル名を表示してしまう*5ので、model 名に日本語を割り当てても「モデル名s」っていう謎の表記になってしまいます。

これは…バグと言った方がいいのかなぁ?

[2010-12-26 追記] 分かりました。

Typus は generate した際に

/app/views/admin/

以下にいろいろ HTML を吐くのですが、その中で

@resource.model_name.human.pluralize

<%= _t(key.constantize.model_name.human.pluralize) %>

こんな記述が出てきます。この pluralize がダメです。

active support の inflection である pluralize は Rails の i18n の守備範囲外なので、model_name.human のあとに呼んじゃダメなのでした。また、Rails の i18n は

5.1 Translations for Active Record Models - Ruby on Rails Guides: Rails Internationalization (I18n) API

にあるように model の名前に対して翻訳を割り当てます。table_name に割り当てる機能があれば .pluralize があっても正しく機能させることも無理ではなさそうですが、現状(3.0.3)ではできません。

model.human のあとに pluralize は呼んじゃダメ

と覚えることにします。

なお、twitter 上で .model_name.human じゃなくて .human_name にすればよかったと書きましたが、human_name は deprecated でした。

残りの課題

ざっと作業だけ見てきましたが、今後の課題は

  • fixture
  • rspec
  • cucumber
  • 「モデルのリレーションシップ」という概念の習得

でしょうか。ORM の利用経験もあまりないため、foreign key を明示せずに Model 中心に考えることがどうもまだしっくりきていません。schema dump してみても

なんだこのスカスカした感じは

というのが率直な感想です。しばらくは戸惑いも残るでしょうが、早く「モデルのリレーションシップ」という考え方に頭を慣れさせないとダメですね。

Tags: Rails Ruby

*1 もともと公開できるプロダクトなんかほとんどないんだけど。

*2 っぽいことを今痛感している最中なのでもしかしたら変なこと言ってるかも

*3 rails g --help とすると確認できる

*4 locale の変更に関しては development 環境でも再起動が必要みたいですね。カタログの変更はすぐに反映されますが。まぁ locale の変更なんて何度もしないので問題ないですけど、知らないと locale が反映されていないのか自分のカタログファイルの用意の仕方がおかしいのか分からないのでちょっと注意が必要です。

*5 正確には model_name をわざわざ pluralize したもの


2010-12-20 [長年日記]

_ 素の Ruby 環境で Fabrication

ダミーデータがたくさん欲しい

自分の仕事場はちょっと変わっているのでダミーのテキストを用意するのはそれっぽい人に頼むと可能ではあるのですが、本来こんなものは機械に作らせればいいのです。とは言えわざわざダミーデータ生成ツールを作るのはダルいし、便利なものも知らなかったので今まではなんとなく人海戦術でやってました。ごめんなさい。

最近ちょっと Rails づいているので fixture replacement の文脈でいくつかデータ生成ツールを見ていた(試してないの多数)のですが、2010冬の段階では Fabrication の人気が上がってきているようですね。(まだ ruby-toolbox.com では名前を見ないけど。)

ということで使ってみた

paulelliott/fabrication - GitHub

まずはよく見る Faker と組み合わせる例。

※ なお、url の部分の処理は参考にした hibariya さんのコード丸パクリです。

気をつけるポイント

Rails 流の Model クラスを想定しているので、この場合は Company クラスのインスタンス変数に読み書きの権限を与えてください。

Fabricate.attributes_for() するなら Struct を使っても結果はまったく同じなので一つの手としてはアリかもしれません。

cf. Fabricationを使ってみた - のどをRubyでいっぱいにして

Faker の代わりに forgery を使う

sevenwire/forgery - GitHub

ruby-toolbox.com の Random Data Generation の項目 では faker よりも forgery の方が人気が高いようですので、こっちも試してみます。

上の Faker の例とまったく同じものを作ってみました。中身を見ると Faker よりもすぐ使えるものが多いからもしかして便利? Formats や Dictionaries が準備されているので Faker よりも作れるダミーデータの種類を増やしやすいのかもしれません。

cf. [sinatra for flasher] 大量のダミーデータを返すAPIを作る - func09

ちなみに今回のコードの全体像

こちら

gist: 748375 - fabrication with faker and forgery- GitHub

git clone して

$ ruby fab.rb -h

で分かりますが、

  • class の生成方法
  • fabrication と組み合わせるダミーデータ生成ライブラリ
  • fabrication で作るデータの形式

を選ぶことができます。

参考

Tags: Ruby RubyGems

2010-12-21 [長年日記]

_ 超今さら初めてのgisty

gisty を知ったのはもう記憶にもないくらい昔だし、直接勧められたのは

Twitter / ゆーけー/赤松 祐希: @wtnabe gistにプロダクトコードとテストコ ...

なんと3月なので9ヶ月前という体たらくでございますが、ようやく使ってみました < gisty

swdyh/gisty - GitHub

必要な準備

  1. gisty gem
  2. GISTY_DIR
  3. git の config
  4. 使っている Ruby が参照できる OpenSSL 証明書

gisty を使うには clone する場所を環境変数で指定しておく。post するだけでも同時に clone するので GISTY_DIR の指定は必須である。

また、git の config は最終的にこんな形になればよい。

[github]
       user  = USERNAME
       token = XXXXXXXXXXXXXXXXXXXXXXX

いずれにしてもエラーメッセージを見ればどうすればよいかは分かるので簡単。

実は、4 でハマった。

Ruby の参照できる OpenSSL 証明書

なんかこれ前にもハマった気がするんだけど、今回は Mac OSX でどうやって解決したか。

gistyをMacから使う - Dive into the Tech World!

を見ると

$ ruby -ropenssl -e 'p OpenSSL::X509::DEFAULT_CERT_FILE'

で、どのファイルを見に行っているか分かる。見るとそこには何もファイルがない。

FreeBSD のとき(Ruby の SSL の証明書検証の失敗でハマっていた - あーありがち(2010-01-14))には ca_root 関係の ports があったけど、MacPorts にはないっぽい。それっぽいのは

$ port search cert
curl-ca-bundle @7.21.2 (net)
    CA certificate bundle for curl

なので、これを入れて

/opt/local/etc/openssl/cert.pem@ ->
      /opt/local/share/curl/curl-ca-bundle.crt

の link を張って対処。

使い方

$ gisty help

で確認できる。(gisty --help ではない。)

gisty post *

としてできあがったのがコレ。

gist: 748375 - fabrication with faker and forgery- GitHub

ふー。長かった。

gisty syncに注意

gisty sync は自分の作った gist 全部を local に clone しようとする。その際、

1回1回鍵の passphrase を聞かれる。

自分は普段 ssh-agent とか使わないのでものすごく面倒になって途中でやめてしまった。

sync の際には ssh-agent や keychain を活用すべし。


2010-12-28 [長年日記]

_ Rinari+RhtmlでRailsのコードを書くことにした

いつものことながらすごく今さらな話。

ずっと ruby-mode.el 一本でやってきたのだけど、Rails のコードはどうも読みにくいし、なんかそう言えば rails.el って聞いたことあったなぁと思い出して調べてみた。結果、

  • rails.el は 2007年で止まっていて事実上の discontinued 状態
  • Rinari という minor mode があるらしい

minor mode で大丈夫なんかいなと思ったけれど、心配無用でした。*1

Rinari

Rinari: Ruby on Rails Minor Mode for Emacs

インストールの注意点

git clone を使って install する際は submodule を要求する。default では git protocol で取得しようとするので git protocol の通らない環境ではインストールに失敗する。

.gitmodules を編集してから submodule を取得しにいけばいいのかもしれないけど、やってみてないのでよく分からない。

Rinari がやってくれること

Introduction - Rinari: Ruby on Rails Minor Mode for Emacs

  • navigation ( MVC や migration 間の行き来 )
  • Web server 立ち上げたり
  • 適切な sql-mode を起動したり
  • テストを支援してくれたり

など。あれ、「読みにくい」という問題は解決しないような。

Rhtml-mode を追加

「読みにくい」のが始まりなので追求。

Add Ons - Rinari: Ruby on Rails Minor Mode for Emacs

んーでも YAML も CSS も JavaScript も困っていないので、追加するとしたら Rhtml かな。

あと yasnippet-rails を入れておいた。(yasnippet はインストール済み)

rhtml-mode の色づけがちょっと気に入らなかったので

M-x customize-group

erb-faces

からちょっといじった。

(custom-set-faces
...
 '(erb-delim-face ((t (:foreground "blue" :weight bold))))
 '(erb-exec-face ((t (:inherit erb-face :underline t))))
 '(erb-face ((((class color) (min-colors 8)) (:underline "black"))))
 '(erb-out-delim-face ((((background dark)) (:foreground "blue" :weight bold))))
...

こんな感じ。

結局 Rails のコードは読みにくいまま

.html.erb は編集しやすくなったし、コード間の移動もやりやすくなった。しかし Ruby のコードは読みやすくならなかった。

Rails のコードはなんていうか helper 以外は宣言的(?)過ぎて、普通のコードのようにメソッドのカタマリを目が認識できない。そのせいかどこで何をやっているのかよく分からない感じになってしまう。少なくとも古い Ruby コードにしか馴染みのない人間にはいささかつらいものがある。もしかするとこれが DSL と騒がれた片鱗なのかもしれないが。

とりあえず何かのツールで劇的に読みやすくなるということはなさそうなので、少しずつ目を慣らしていくしかないみたい。

とは言え Rinari は便利。収穫アリ。

*1 ほんとの最先端は Rinari じゃないらしいんだけど、ほとんどのツールで先端を追ってない自分にはまったく問題ない。