ということで久しぶりに trunk のソースツリーを svn up。というところで、そういえば 1.9.1 の release candidate 2 のリリースがアナウンスされていたなとふと思い出したので、仕事のプロダクトが 1.9 でどの程度動くかまた挑戦してみることにしました。半年前くらいに挑戦した時は確か Thread.critical に依存しているところがあってすぐに動かせなかったのですが、そのコードは書き換えられたので今度はそこそこいけるんじゃないかと思ったので。
なので 1.9 への移行の経験談としてちょっと残しておきます。
- とりあえず magic comment は全部つけておく。
- IO.read 等で読み込んだ String に encoding が付いていることによる問題
- m17n関連の対応その2。
- これはたとえば、String#length が文字コードを認識してくれて、バイト数じゃなくて文字数を返すようになったこととか。
- あとそもそもバイナリを期待しているものを EUC-JP として読んでいることがだめなわけで、そのへんもなんとかしないといけない。
- 例えば IO.read で読み込みサイズを指定しない呼び出しだと、勝手に Encoding.default_external のエンコーディングになってしまう。
- IO.read(filepath, :conding => "ASCII-8BIT") のようにオプション引数(ただのハッシュだけど)で指定するといいらしい、でもこれは 1.8 では動かない。Kernel#open も、第二引数に "r:utf-8" のように書けばいいらしいけどこれも 1.8 では動かない。もしかして open(filepath, "rb") なら ASCII-8BIT になるのかなと思ったらどうやらそうではないらしい。まあこれは改行コードの扱いの指定だからかな?
- そんなわけで 1.8 でも動くようにしつつ、あんまりたくさん書き換えずにすむ対処法としては、Encoding.default_external= で ASCII-8BIT を指定するという方法でした。
- プロダクトは ruby インタプリタを常にラッパ経由で起動するようになっていたので、コマンドラインオプションに -EASCII-8BIT を追加することで対処できました。
- でもなんか過去の ruby-dev の議論をぼんやり眺めていた印象としては ASCII-8BIT を多用するのはあまりよくないことなのかも。本当はスクリプトをちゃんと確認して、必要なところで適宜 encoding を指定したり、bytesize 等適切なメソッドを使うという対処をしたほうがいいのかもしれません。
- しかし 1.8 では常に ASCII-8BIT だったというのとだいたい同じなんじゃ? だったら 1.8 向けのスクリプトは Encoding.default_external = "ASCII-8BIT" でファイル等からの読み込みのぶんについては OK なんじゃないのかな? magic comment をつけたスクリプトの中の文字列リテラルの問題もあるけど。
- ちなみに今回対応させたプロダクトはコメント以外は日本語を使っていない(us-ascii)ので m17n の問題の影響は少ないほうだと思う。よく知りませんが日本語の正規表現のこととか、どんなことになるのかぞっとしますね。
- classx の verification で一部 :default に定数を渡しているところで動かなかった。
- 定数の検索が変化したんだったか。でも :default => lambda { Const } のように Proc で包むと回避できました。うーん、もうちょっと調べておきたい。
- { 1, 2, 3, 4 } => { 1 => 2, 3 => 4 } というリテラル記法が廃止された影響
- 誰だよこんな記法を見付けてきて使ったのは……。即修正。
- termios 拡張ライブラリが 1.9 に未対応(RubyGems版)
gem install termios がエラーになったというだけでよく調べていません。http://arika.org/ruby/termios によると 0.9.5 で 1.9.1 対応のパッチを取り込んだとあるんだけど……。これも追加調査が必要。(追記:確かに tarball 版の 0.9.5 はあるんだけど、RubyGems版はまだ 0.9.4 みたい。gem パッケージは誰が作っているんだろう。)- でもとりあえず依存してる部分をコメントアウトした。
- Find.find が渡されたディレクトリが存在しないときに Errno::ENOENT を raise するようになってた。1.8 では黙ってブロックを yield せずに返ってきてた。
- まあ多分正しい挙動になったということなのだろうから Find.find する前にチェックするように。
だいたいこれくらいやったら、とりあえず動いたかもという状態にはなりました。多分まだ細々としたところが残ってるでしょう。やっぱり encoding 関連が一番インパクト大きいかなという印象。
これだったら差し替え版でフルテスト流してみて移行できるか評価してみようという話にもっていけるかも。正直 1.9 系を本気でプロダクトで使ってリリースするのはまだ早いんじゃないかとも思いますが、1.9 にすると速度面や Hash の順序保存、それと地味に iseq をダンプしたものを読み込むとか、かねてから要望があったものの 1.8 では実現の難しかった項目が解決 or 対応の可能性ができるので、けっこうアピールできるかも。安定版だってバグがないわけじゃないし。できれば 1.9.1 の正式リリース前に踏めるバグは踏んでおきたいし。
(追記) デブサミ2009で yugui さんが 1.9 の導入について話すらしいからぜひ聞きに行こう。