「JRuby on Rails」について発表しました

昨日の4月30日、JJUG主催による「クロスコミュニティカンファレンス」にて、「JRuby on Rails」というお題目で話をしてきた。

聴衆の中に潜んでいたJRuby第一人者から、手痛い突っ込みの数々を頂いた。ここで上記資料の中で訂正(ってわけじゃないけど)してみようと思う。

  • 32枚目の「CGIに比べてパフォーマンス的に有利」と記述してしまったが、現状ではmongrel_clusterで真面目に(?)構築した方が、JRubyよりもパフォーマンスはいい数値が得られている、とのこと。僕が実測したときには、初回のアクセス以外はかなりレスポンスは良かったのだが、全体的にはまだまだ、という印象のようである。
  • 33枚目でセッションのクラスタリングの話をしたのだが、現在のJRuby+GoldSpikeでは、普通にJavaのHttpSessionを使ってくれるので、普通にAPサーバのセッションクラスタが効くよ、とのこと。
  • 39枚目で、include_classを使っているが、現在はimportを使うよ、とのこと。

というわけで、上記に読み替えてスライドを見て欲しい。会場にきてくれた皆さま、申し訳ございません。いろんな方々から「わかりやすくて良かったよ!」と感想を頂いていただけに、ホントに恥ずかしい限りである。。。

ActiveResourceで拡張子なしのURIを発行する方法

Ruby on Rails 2.0から標準搭載されたActiveResource。これを使うと、RESTful APIをActiveRecordのように叩くことができるようになる。自分でURIを作ってopenすることもせず、レスポンスを自分でパースしてオブジェクトを作ることもせず、数行の記述でRESTfulなサービスを利用することが可能になる優れものだ。ActiveResourceの詳細は、ここを見て欲しい。

さて、現状のActiveResourceは、僕にとって一つ気になる点がある。それは「URIが必ず拡張子付きで発行される」という仕様。例えば、

として、「Community.find(1)」と実行すると、

GET http://commusuke.eisbahn.jp/api/communities/1.xml

というURIでRESTfulサービスにアクセスしにいく。つまり、接尾語として「.xml」が自動的に付加される。これにより「レスポンスはXML形式で返してね」という意思表示になる。ちなみにこの拡張子は、format=メソッドを使って変更することができる。例えば、

としてあげて「Community.find(1)」と実行してあげれば、

GET http://commusuke.eisbahn.jp/api/communities/1.json

というURIが発行され、「JSON形式で返してね」という意思表示を行うことができる、という機構。

では「.xml」も「.json」も付けず、

GET http://commusuke.eisbahn.jp/api/communities/1

というURIでアクセスを行いたいとする。もちろんRESTfulサービスの中には、拡張子付きのリクエストを受け付けず、固定でXML形式のレスポンスを返してくる、という局面も存在するわけである。しかし、現状のActiveResourceでは、必ず何らかの拡張子を付けてURIを組み立てる、というコーディングになっていて、つまり拡張子付きを受け付けないRESTfulサービスを利用することはできない、ということになっているのだ。ちなみに、「self.format = nil」とかやってもダメ。

では、拡張子がないURIに対応するためのパッチを書くことができるかどうか、やってみることにした。結論から言うと、拡張子をつけないようにするこことができた。以下に、そのためのコードを紹介してみる。

まず、「self.format = :json」というように指定した結果、ActiveResource::Formatsモジュールに属しているフォーマッタモジュールが実際には適用される。XML形式とJSON形式が標準で搭載されていて、

  • XML形式 – ActiveResource::Formats::XmlFormat
  • JSON形式 – ActiveResource::Formats::JsonFormat

という対応になっている。上記のフォーマッタモジュールでは、下記のメソッドがそれぞれ定義されている。

  • extension – 拡張子を返す。
  • mime_type – MIME種別を返す。
  • encode – 受け取ったオブジェクトをエンコード(XMLやJSONに変換)する。
  • decode – 受け取った文字列をデコード(ハッシュに変換)する。

まずは、XML形式なんだけど拡張子はなし、というモジュールを自作する。XmlFormatモジュールを継承(?)して作ってみる。XmlFormatのメソッドはそのままに、extensionメソッドのみ再定義してnilを返却するようにしている。これは、例えば「app/controller/application.rb」ファイルの最後に書いておけば良いだろう。

format=メソッドに渡すシンボル(:xmlとか:jsonとか)は、camelizeされたものに「Format」が付けられた名前(:xmlならXml+Format)のモジュールが適用されるようになっている。つまり、上記のXmlNotExtensionFormatモジュールを使用したい場合は、

というように指定してあげれば良い。これにより、拡張子が取り除かれたURIが作られる。

・・・と思いきや、世の中そんなに甘くなかった。extensionメソッドがnilを返したことによって「xml」という文字は取り除かれるようになるのだが、「.」が残ってしまう。つまり、

GET http://commusuke.eisbahn.jp/api/communities/1.

となってしまうのだ。惜しい。実に惜しい。

URIを構築しているのは、ActiveResource::Baseクラスに定義されているelement_pathおよびcollection_pathという2つの特異メソッドである。例えばelement_pathメソッドのコードを見てみると、非常に残念なコードであることがわかる。

これでは「.」を取り除くことがフォーマッタモジュールの頑張りだけでできないことがわかってもらえるだろう。解決策としては、これら2つのメソッドを置き換えるしかない。具体的には、

というコードを、例えば先ほどと同じように「app/controller/application.rb」ファイルの最後に記述してあげれば良い。これにより、適用されたフォーマッタモジュールのextensionメソッドがnilを返したときは、拡張子も「.」もないURIが発行されるようになる。めでたしめでたし。

もし「.xmlとか.json付けられないのにActiveResourceでアクセスしなきゃならねーんだよ」的なことになったら、上記のコードを利用してみて欲しい。

map.resourcesでcollectionを指定すると.xmlを受け付けない、なんてことはなかった

RESTful APIをRuby on Railsで実装するための重要な機構に、map.resourcesがある。これはconfig/routes.rbファイルで記述され、URIに関してRESTfulなプロトコルに対応した処理のマッピングを自動的に設定してくれる仕組みだ。例えば、

としてあげれば、「GET /articles/1.xml」というリクエストに対してArticleController#showメソッドが、「DELETE /articles/1.xml」というリクエストに対してArticleController#destroyメソッドが呼び出される、といった具合になる。たった1文でこんな設定が実現できるのは、非常に嬉しい。

さて、上記の例では、URIの最後に「.xml」という拡張子をつけている。これは「レスポンスはXML形式で返してね」という指示を意味する。URIに拡張子を付けなくても、リクエストヘッダのAcceptフィールドでレスポンスの形式を指定することもできる。つまり、上記の設定は、「GET /articles/1」でも問題なくArticleController#showメソッドが呼び出される。

Railsで想定されるRESTful APIは、上記のような「/リソース名/ID」という指定が基本となる。しかし、例えば「GET /articles/rss」というように、ID値指定ではなく、意味のある単語でURIを構成したいこともあるだろう。そのような場合には、map.resourcesでの記述は、

というようにすれば良い。これにより、「GET /article/rss」というリクエストに応じて、ArticleController#rssメソッドが呼び出されるようになる。

しかしRails 1.2.6では、:collectionを指定した際に、「GET /article/rss.xml」というように拡張子を付与した形でリクエストを投げても、認識されずに404となってしまう。もちろん「GET /article/rss」でAcceptリクエストヘッダを指定すれば、レスポンスの形式を指定した上でArticleController#rssメソッドがちゃんと呼ばれる。しかし、「GET /article/rss.xml」とか「GET /article/rss.json」とか「GET /article/rss.atom」とか指定しても、404。

これはさすがにバグな予感がするので、Rails Tracにチケットを発行して登録してみた。

Ticket #10960 「:collection of map.resources doesn’t recognize the extension of URI」- Rails Trac

この問題、別にAcceptリクエストヘッダを使えばいいだけの話なのだが、現状のActiveResourceは、内部で生成されるURIに必ず「.xml」や「.json」などの拡張子が自動的に付いてしまうため、「GET /article/rss」を呼べないのだ。つまり、Railsで作ったRESTful APIなのに、Railsに含まれているActiveResourceでアクセスできない、ということになってしまう。これは余りにもダサい。。。

Rails 2.0でどうなのかは試してないので、もしかしたら上記の問題は発生しない、かも。あとで試してみることにする。

追記:2008年1月31日

どうも僕のmap.resourcesの書き方が間違っていたみたいで、シンプルなアプリを作って検証したら、Rails1.2.6でもRails 2.0.2でもちゃんと拡張子付きで処理された。よって、上記チケットもclose。自分の確認力のなさに絶望。。。orz

JRuby-1.0.3のRegexp#escapeメソッドは文字コードを指定できない

JRubyの現在の正式な最新バージョンは1.0.3である。しかし、1.1RC1も登場しているので、1.1の正式版が登場するのは時間の問題だろう。安定版ということで1.0.3を使いたくなるし、多くの場合は1.0.3で事足りるだろう。しかし、今日僕は1.0.3で小一時間ハマってしまった。

そろそろこみゅすけの携帯版を作ろうと思い、jpmobileというプラグインをRails 2.0にインストールしていろいろと遊んでみることを始めようとした。もちろんJRuby-1.0.3のgemでRails 2.0.2をインストールし、railsコマンドでプロジェクトファイル一式を生成、そしてscript/plugin installでjpmobileをインストールして、script/serverでいつものようにWEBrickを起動しようとした。

しかし、悲しいことに、エラーメッセージが表示されてしまい、WEBrickは起動しない。

=> Booting WEBrick…
/Applications/java/jruby/jruby-1.0.3/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:499:in `require’: wrong number of arguments(2 for 1) (ArgumentError)
  from /Applications/java/jruby/jruby-1.0.3/lib/ruby/gems/1.8/gems/rails-2.0.2/lib/commands/server.rb:39
  from /Applications/java/jruby/jruby-1.0.3/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’
  from /Applications/java/jruby/jruby-1.0.3/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’
  from :1

調べてみると、vendor/plugins/jpmobile/lib/jpmobile/emoticon/z_combine.rbファイルの中でエラーが発生していることがわかった。具体的には、以下の行で引数の個数が合わない、というエラーが発生していた。

この行のどこがエラーになっているのか、script/consoleを使って確かめてみる。すると、

というように、エラーを再現させることに成功。なんと、Regexpクラスのescapeメソッドが引数を2つ受け付けない、ということが判明した。確かに、JRubyのソースコードを追っていったところ、RubyRegexp.javaファイルにおいて、

という記述しか見つからず、文字列一つを受け取るescapeメソッドしか定義されていない。

ここで、Regexpクラスのescapeメソッドは、quoteメソッドと等価であることに気がつく。では、quoteメソッドも同じなのか?

一瞬「お、quoteメソッドは大丈夫じゃん」と思ったのもつかの間、なんとUnicodeしかサポートしないよ、と警告されてしまった。これじゃあ第2引数を渡しても、実質意味がない。

まとめると、JRuby-1.0.3では、

  • Regexp#escapeメソッドでは、渡した正規表現の文字コードを指定できない。
  • Regexp#quoteメソッドを使用して文字コードを指定しても、そもそもUnicodeしかサポートされない。

ということであり、自分でRubyRegexp.javaファイルをいじるなりしなければ「GAME OVER」という結論になってしまった。このメソッドが使用される局面は、普通のWebアプリケーションではそんなにないだろうけど、少なくともjpmobileを使った携帯サイトは、JRuby-1.0.3では構築できない。当然だけど、Rails 1.2.6でもNGであり、CRubyの1.8.6ではちゃんと動作する。

ちょっと悔しいので、JRuby-1.1RC1でもダメなのか?という検証を行ってみた。結論としては、上記の問題は解決されていて、Regexp#escapeメソッドとRegexp#quoteメソッドの両方とも、第2引数をちゃんと受け取るし、指定した文字コードが正しく処理に反映されているようだ。JRuby-1.1RC1、Rails 2.0.2、そしてjpmobileのtrunkという組み合わせで、ちゃんとWEBrickも起動するし、「mobile_filter :hankaku => true」として半角カナ変換も機能している。絵文字は試してないけど、たぶん大丈夫だろう。

というわけで、JRuby-1.0.3は、文字コードの扱いが非常に惜しいレベルであることが判明してしまった。が、JRubyコミュニティも1.1シリーズに今後力を注いでいくだろうから、もしJRubyでRailsするなら、すでに1.1系を使っていくことが現実解だということなのだろう。

イルカが太陽に取り込まれる日

OSSなデータベースの代表格「MySQL」が、米Sunにより買収されるらしい。
米Sun、オープンソースDBのMySQLを買収へ」- Enterprise Watch
PostgreSQLの性能向上によってMySQLを選択する理由が次々となくなってきている今、MySQL陣営にとっては嬉しいニュースなんじゃないかな。これによって、MySQLのエンタープライズ領域(つまり大規模案件への適用)での事例が増えてノウハウが次々とオープンになってくれば、PostgreSQLにシェアを食われている率も下がるんじゃないだろうか。
Ruby on Railsの最新バージョンがMySQLをデフォルトDBにするのをやめてしまった件は、この買収と関係があるのだろうか。例えば、DHHはこの買収劇を事前に知ってたってことなのかしら?

僕のCode to Test Ratio歴

Ruby on Railsでの開発では、その規模の大小問わず、短期的・長期的問わず、最低限の品質を確保するためにテストコードの作成と自動化は「必ず」行うべきである、という考えを僕は持っている。つまり、テストコードのないRailsの成果物は、非常識きわまりなく、構造計算が一切行われていない建物と一緒。もしそんな開発プロジェクトがあれば、それは国会で取り上げられる程の騒ぎにならなければいけない事態であり、IT業界からご退場願わなければならない、と思っている。

さて、RoRでは、常に「自分がテストにどれくらい関わったのか」という指標を確認できるように、rake statsというタスクが標準で提供されている。これにより、実装コード行数とテストコード行数の割合がサクッと出てくる。もちろんカバレッジ率ではなく、総行数に関する指標であるので、あくまで参考値ではあるが、それを意識するのとしないのとでは大違いだろう。

rake statsは、railsコマンドでプロジェクト一式を生成した直後から使用することができる。

こんな感じで出力される。Code to Test Ratioの数字は、実装コードの総行数を1とした場合の、テストコードの総行数の割合、である。この数字を意識することが必要。

では、この数字を評価するための参考値が何かあるのか?というと、お堅い大企業ではよく品質管理部門が「1関数あたりに必要なテスト項目数」とか決めていたりするけれど、ことRailsでのそういった指標をGoogleで探しても、参考になるような情報は見つけられなかった。

なので、僕がRailsで開発したものについて、Code to Test Ratioの数字(これは客観的な指標)と、テストをやりきったかどうかの感覚(これは僕の主観的な指標)をここにいくつか提示してみよう。

  • ToDo管理アプリ – 1:3.1 – これでもかっとテストコードを書いた。
  • ブックマーク共有アプリ(承認機能付き) – 1:1.4 – ロジック・画面遷移・各メソッドについてはほぼ網羅。しかしViewに関するテスト(動的内容が正しいタグの場所に出力されたか)は甘かった。
  • facebookアプリ – 1:2.3 ほぼテストコードを記述。しかしFacebook APIを利用する部分のテストが甘い。

非常に少ないケースから、さらに主観的な傾向を読み取るとしたら、

  • 3.0〜 – ほぼ大丈夫。安心レベル。
  • 2.0〜3.0 – 一部抜けがあるものの、運用を継続できるレベル。
  • 1.0〜2.0 – テストコードはあるが、大きく抜けている部分がある可能性大。運用開始はできても継続成長は無理。
  • 0.0〜1.0 – 話にならない。運用開始直後から多数の不具合が発見されること確実。

という感じになる、かな。

もしRuby on Railsを使って作られたサービスやシステムで、rake statsにより得られたCode to Test Ratioの値が、例えば「2.0」を下回っていた場合は、そのシステムの開発ベンダーに今すぐに問い合わせをすべきだ。そして、不幸にも最も酷い「0.0〜1.0」の範囲内だった場合は、開発ベンダーによる詐欺行為を受けていると認識して構わない、と考えて良いと思う、個人的には。

良い子のみんな、上記が「理想論」とか「学術的」とか、決して思わないように。上記は、システム開発をする上で「最も当然」なことであり、それが信頼感、達成感、安心感、責任感を顧客に提供することになり、初めて「ビジネス」という言葉が使えるようになるんだ、という考えで、Ruby on Railsというものに取り組むべきである。僕はそう考える。

Fixtures Visualizerプラグインを公開しました

あけましておめでとうございます。今年もよろしくお願いいたします。

2008年の最初のエントリは、新年の挨拶もほどほどに、この冬休みの宿題の1つの成果報告をしてみよう。4つほどあった宿題だが、結果が出たのは1つのみである。なんとも情けない。。。

さて、昨年さんざん騒がれたRuby on Railsだが、「Javaな感覚」でRailsアプリを作ると、それはすなわち「Java以上の失敗プロジェクト」になる。「Javaな感覚」とは、つまり、コンパイラの存在。Javaにおいて、コンパイラが行ってくれる文法チェックやクラス間の依存性検証は、プログラマに対して非常に大きな安心感を与える。もっと言えば、非常に低いレベルとは言え、単体テストコードがなくても、コンパイラがあればなんとかリファクタリングができてしまうことも多いだろう。

しかし、Rubyにはコンパイラなどない。Railsの場合、プログラマがどこで保険を得れば良いか?そう、単体テストコードである。Javaのコンパイラが担っている作業は、Railsでは全て単体テストで実施しなければならない。そのため、Railsは単体テスト環境において非常に手厚いサポートを提供してくれている。このサポートによる単体テストの気持ちよさがあったために、僕はJavaよりもRailsを使うようになったと言える。

そんなRailsの単体テスト環境では、テストデータをfixturesという機構で準備する。このfixtures、実体はYAML形式のファイルである。例えば、

といった感じの内容になる。モデルクラス(=データベースの表)1つに対して、fixturesのYAMLファイル1つが対応する。つまり、データベースの表の数だけfixturesファイルが作成される。

もちろんRailsが対象にするのはリレーショナルデータベースなので、複数の表の間に関連がある。例えば、Departments表とEmployees表は、従属の関係があり、特にRailsの場合は、Employee表にdepartment_id列があることになる。department_id列の値が、Departments表の行、つまり所属部署を示すことになる。ま、当たり前の話だが。

この関連、fixtures上で管理するのは非常に難解な作業となる。ただでさえ列の値で関連を追うことが難しいのに、表ごとに分かれてしまっているテキストファイルであるため、ちょっと数が多くなれば、すぐにメンテが苦痛になってきてしまうだろう。せっかくの便利な機構が、これでは台無しになってしまう。fixturesの内容、特に関連について視覚的に把握できるようになれば、fixturesのメンテナンスや、それを元にした単体テストコードの記述がしやすくなるのではないだろうか。

そんな動機から開発してみたのが、Fixtures Visualizerプラグインである。ベタベタな名前が示す通り、fixturesの内容を視覚的に表示してくれるというプラグインだ。最初は、fixturesの内容をXMI形式でエクスポートし、それを各種UML作図ツールにインポートして閲覧する、というストーリーを考えていたのだが、あまりのXMIの仕様の難解さ&ツール独自仕様の氾濫さに嫌気が差して断念。その代わりに、Open JacobのDraw2Dライブラリを使って、Webブラウザ上でfixturesの内容をUMLのオブジェクト図ちっくに見れるようにした。

Trac: Fixtures Visualizer

インストール方法は、上記のページの[Install]の項目を、使い方については同じく上記ページの[Usage]の項目を参照して欲しい。ま、プラグインをインストールして、「http://localhost:3000/fixtures_visualizer」というURLにアクセスするだけの簡単な手順である。以下のような感じで、fixturesが見れるようになるはずだ。

fixtures_visualizer.jpg

Version 1.0としているが、いくつかのアルゴリズムがヘボいために、fixturesのファイル数およびその中に記述されているデータ数が多くなると、Webブラウザが固まってしまうことや、モデルのDrag&Dropでの移動がもたついてしまう、といった現象が発生する。今後改良を重ねていって改善していこうと思っている。

Railsを使った開発で「fixtures地獄」に悩まされている人々に対して、少しでもこのプラグインが役に立つことを願っている。2008年最初の僕からの成果物、皆さんからのご意見、ご感想などを聞かせて頂けると、とっても嬉しい。

ちょっとだけ余談。本当に不思議に思えてならないのだが、もっとテスト環境の良さをRails関連のコミュニティは訴えるべきなのに、そういうコミュニティは非常に少ない。「Railsだと立ち上がりが早いです」なんて言ってRailsを勧めているコミュニティは、今年中に滅んで欲しいと切に願う。末長くサービスを成長させて公開し続けるための施策こそが、Railsの重要な部分なのに、それに触れずに開発初期の立ち上がりの話のみに終始するなんて、100%ナンセンス。多くのJavaのプロジェクトで真面目に行われることが希少な単体テストのための工数をしっかり積まないといけないため、一般的なJavaなプロジェクトと、ちゃんとしたRailsなプロジェクトは、そう工数に違いはない or Railsの方が多くなるはず。単体テスト環境に触れないRails関連の勉強会があったら、それは使えないプログラマを量産していることになる。良い子のみんなは、そんな勉強会に行かないように。

railsとrakeは似ている

Railsアプリのディレクトリの中で、テストケースを実行するために、
rake test
と打たなければならないところを、
rails test
と打ってしまうと、もれなくtestアプリケーションがテスト対象アプリの中にできあがる。
Railsアプリを「正しく」作っている(=ちゃんとテストコードを書いて品質を担保している)人々はきっと経験していることではないか、と想像してみるが、いかがだろうか。。。

丸レクでREST on Railsについて話をしてきました

本日、「丸山先生レクチャーシリーズ RESTfulサービス技術の台頭」で話をしてきた。僕の題目はというと、「Ruby on Rails2.0におけるREST対応」。使用したスライドは下のものである。

PDFはこちら
個人的には、やっぱり練習をしていくべきだったかなぁ、と、話し方に関して反省である。何度もRESTとRailsを言い間違えたし、日本語として正しくないよなぁ、と思ってしまうほど文法上酷い言い方をしてしまった部分もあった。しかも、かなりの早口になっていたはずで、45枚あるスライドで、しかも途中でデモもやっているのに、時間が余るって何だよ、ってことになってしまった。まだまだスキルが僕は足りないな、と痛感。
しかし、会場に来ていただいた方々からのアンケート結果は、意外にも高評価。「わかりやすかった」「RailsでのREST対応があんなに簡単だとは思ってなかった」という嬉しい意見を頂くことができた。「聞き手側にわかりやすく説明していた」というのが、昨日の僕にとって最高の褒め言葉だった。とりあえず、役目は果たせたのかな、と。
講演が終わって、僕が「あっさりとActionWebServiceをRails2.0になって捨てました」と言ってしまったのが気になったのか、「Railsは3.0になってもそういう姿勢なのか?」という質問を頂いた。正直に言うと、僕はRails3.0なんてどうなってるかわからないけど、今後も時代の流れに従って、標準として搭載するものははっきりとした方向性を出していくのではないか、と答えた。そして、もちろんActionWebServiceがなくなってしまったわけではなく、別途インストールは可能である、とも付け加えた。
丸レク終了後、個別に質問を頂いた。ここに情報共有してみる。

Q. 〜.xmlとか〜.atomとするのがRailsなのか?これはRESTに関して一般的なのか?
標準規約がそうなだけで、これを無視することもできるし、routes.rb次第で如何様にもなる。現に、僕は〜.xmlが(理由を聞かれると困るけど)好きではないので、単に「/employees/1」というリクエストにはHTMLではなくXMLで返すように実装してしまう、と答えた。
Q. DELETE /employees/1.xml を受け取ったとき、すでにそのリソースが存在しなかった時に返却する値は、404ではなく、204(No Content)では?
一般的にGETによる対象リソースがなかった場合は404を返す。ネットや書籍でいろいろ調べた結果、DELETEについても実装例で最も多かったのが404だったため、そのように説明した。しかし、確かに204を返して、20xシリーズ(=成功レスポンス)を使うのが好ましいかもしれない。ま、DELETEしようとして既にリソースがない場合は、それをエラーとして扱ったところで何もすることはないため、200でも構わないかもね、と話をした。

Rails2.0.2になり、MySQLが標準ではなくなるなど、さらに進化が続いている。Project ZeroやJava API for RESTful Web Servicesの動向も気になるところだが、やはり実践という点では、Rails2.0に軍配が上がっているのが現状だと感じる。
会場にいらしていただいた方々、ありがとうございました。今後ともREST on Railsを注目してみてください。

Rails2.0.2がもうあるよ!

JRuby1.0.3がリリースされたので、それにRailsを入れようとした。
rails202.jpg
なんと、すでに2.0.2がある。この前2.0.1がリリースされたばかりなのに。
というわけで、近日中に2.0.2リリースのアナウンスが正式に来るだろう。

Get Adobe Flash playerPlugin by wpburn.com wordpress themes