at posts/single.html

Ruby 1.9.0 の ERB ではテンプレートの encoding が欠落する

やっぱりさっきの予想は的中。以下のソースで確認した。

require 'erb'

data = "データ"
rhtml = "テンプレート + <%= data %>"
erb = ERB.new(rhtml)

puts "data: #{data.encoding}"
puts "rhtml: #{rhtml.encoding}"
puts "erb.src: #{erb.src.encoding}"
puts erb.result(binding)

このプログラムを --encoding=ETC-JP オプションをつけて実行する。

 $ ~/local/bin/ruby --encoding=EUC-JP  test.rb
data: EUC-JP
rhtml: EUC-JP
erb.src: ASCII-8BIT
(erb):1:in `concat': character encodings differ (ArgumentError)
        from (erb):1:in `<main>'
        from /home/machu/local/lib/ruby/1.9.0/erb.rb:743:in `eval'
        from /home/machu/local/lib/ruby/1.9.0/erb.rb:743:in `result'
        from test.rb:14:in `<main>'

ERB.new の引数で渡したときは EUC-JP なのに、内部でコンパイルすると ASCII-8BIT になっている。 それで、 ASCII-8BIT のソースを eval で実行するときに、 EUC-JP な data を埋め込もうとしてエラーになると。

ERB の仕組みが分かっていないけど、とりあえず以下のパッチで対処した。

$ diff -u erb.rb.org erb.rb
--- erb.rb.org  Fri Dec 28 23:05:02 2007
+++ erb.rb      Fri Dec 28 23:05:18 2007
@@ -689,6 +689,7 @@
     compiler = ERB::Compiler.new(trim_mode)
     set_eoutvar(compiler, eoutvar)
     @src = compiler.compile(str)
+    @src.force_encoding(str.encoding)
     @filename = nil
   end

今度は期待した動作になったよ。これで先に進めるかな。

$ ~/local/bin/ruby --encoding=EUC-JP  test.rb
data: EUC-JP
rhtml: EUC-JP
erb.src: EUC-JP
テンプレート + データ

関連する日記