よたらぼ
自分の興味の赴くままにIT技術系のネタを取りとめもなくメモっています。
Ruby言語やLinuxのネタが多いです。

September 14, 2006 [おもひで]

[Ruby] Ruby-GetTextを使うとrake でRDocタスクが失敗する

と質問がありました。これは以下のようにすると回避できます。

desc "Update pot/po files."
task :updatepo do
  require 'gettext/utils'  #Here!
  GetText.update_pofiles("blog", Dir.glob("{app,lib,bin}/**/*.{rb,rhtml}"), "blog 1.0.0")
end
 
desc "Create mo-files"
task :makemo do
  require 'gettext/utils'  #Here!
  GetText.create_mofiles(true, "po", "locale")
end 

つまり、'gettext/utils'をupdatepo/makemoタスクのいずれかでしか動かさない、というものです。

これ、Ruby-GetText側で何らかの対応しようと思ったんですけど、やめました。

調べてるときに気づいたのですが・・・RDocの実装、ひどすぎです。今回の問題はRubyのソースに含まれるrdoc/parsers/parse_rb.rbにあると断言します。なぜって、これ、irbに含まれるライブラリのコピペですYO!

せめてサブクラス作ってオーバライドするなりすれば良いのに、なぜ、思いっきりコピペなんだ・・・・。

irbのパーサを使っているGetTextをrdocタスクと一緒にrequireすると、どちらか片方が定数値の重複定義エラーになるわけです。

以下のようにするだけで簡単に再現します。

% irb
irb(main):001:0> require 'rdoc/rdoc'
/usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:31: warning: already initialized constant EXPR_BEG
/usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:32: warning: already initialized constant EXPR_MID
/usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:33: warning: already initialized constant EXPR_END
/usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:34: warning: already initialized constant EXPR_ARG
/usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:35: warning: already initialized constant EXPR_FNAME
/usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:36: warning: already initialized constant EXPR_DOT
/usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:37: warning: already initialized constant EXPR_CLASS
/usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:262: warning: already initialized constant TokenDefinitions
/usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:267: warning: already initialized constant TkReading2Token
/usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:268: warning: already initialized constant TkSymbol2Token
NameError: uninitialized constant RubyToken::AlreadyDefinedToken
        from /usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:273:in `def_token'
        from /usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:300
        from /usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:299:in `each'
        from /usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:299
        from /usr/lib/ruby/1.8/rdoc/rdoc.rb:8:in `require'
        from /usr/lib/ruby/1.8/rdoc/rdoc.rb:8
        from (irb):2:in `require'
        from (irb):2
        from /usr/lib/ruby/1.8/rdoc/parsers/parse_rb.rb:1275
irb(main):002:0>

irbのパーサ使わずにripper使うのが王道、ってことなのかもしれないけど、せめて、標準ライブラリは同時に全てを呼び出してもバッティングしない(まぁ、どうしても避けられないパターンはあるかもしれないけど)ようにすべきだと思うんだけどな・・・。

ひとまず、Ruby-GetTextとしては、タスク毎にrequire 'gettext/utils'することを推奨としますか・・・。ちょっと釈然としないけど。


編集