今日やったRuby 1.9への移行方法

rcodetoolsRuby 1.9に対応していなかったので、手許のバージョンで対応させておいた。そろそろリリースしないといけないな。
rct-completeコマンドはRubyのメソッド等を補完するプログラムなのだが、「Object#methods」などが文字列ではなくてSymbolを返すことの影響をもろに受けてしまった。たとえばmethが文字列だとして、「Kernel.instance_methods(false).include? meth」なんてコードを実行したらRuby 1.8では動いてもRuby 1.9では動かなくなってしまう。だから「Kernel.instance_methods(false).map{|x| x.to_s}.include? meth」のようにmapで文字列化しておく。これで互換性は保てる。「Enumerable#stringify」なんてのを定義してもよい。

module Enumerable
  def stringify
    map{|x| x.to_s}
  end
end

さらに、StringがEnumerableではなくなったのが「ぎゃーーーー」ってレベルの大騒ぎだ。だから「alias :each :each_line」と「include Enumerable」しておく。もう定番かな?あと、Ruby 1.8であった「Enumerable#enum_with_index」がなくなってしまったので「Enumerable#each_with_index」の別名にしておいた。
Ruby 1.9ではブロックなしの「each_with_index」は「enum_with_index」と同じ働きをするからだ。
「Array#to_s」がinspectの挙動になっているので、強制的にjoinの別名にしておいた。
まとめるとこんな感じ。

if RUBY_VERSION >= "1.9"
  class String
    alias :each :each_line
    include Enumerable
  end

  module Enumerable
    alias :enum_with_index :each_with_index
  end

  class Array
    alias :to_s :join
  end
end

Ruby 1.8用に書かれたスクリプトRuby 1.9でも動くようにする「compat.rb」という移行支援スクリプトでも作ろうかな?