tDiary2.2 for Ruby1.9.0
2008-01-23
昨年末から tDiary2.2 を Ruby1.9.0 で動かそうとしている。
なんとか形になったので、思い切ってこの日記を Ruby1.9.0 で動かすように切り替えた。 フッタの「Powered by Ruby version 1.9.0」に注目。 一応動いているけど、正直、何が起こっても不思議じゃない。 何かあればツッコミしてもらえると嬉しいなぁ。 ちなみに、ちゃんと Ruby1.8 とも共用できるようになっているはず。
方向性は以下の通り。
- 一つのコードで Ruby1.8 と Ruby1.9 に両対応する
- 非互換の部分は極力 compatible.rb でカバーする
- Ruby1.9 は —encoding=Binary で動作させる
自分が使っているプラグインは一通り動いたけど、それ以外のは分かんない。
インストール方法
- tdiary-full-2.2.0.tar.gz を取得する
- tdiary-core-2.2.0.patch と tdiary-plugin-2.2.0.patch を当てる
- compatible.rb を misc/lib に入れる
- 起動オプションに —encoding=Binary を付ける
- cache ディレクトリの *.parser を削除 (PStore は基本的に互換性ないはず)
これらのファイルを CodeRepos に置きたいんだけど、どこに置けばいいかなぁ。
以下、変更点の説明。
compatible.rb
Ruby1.9 で無くなったメソッドを復活させる。
unless "".respond_to?('to_a')
class String
def to_a
[ self ]
end
end
end
unless "".respond_to?('each')
class String
alias each each_line
end
end
class String
def method_missing(name, *args, &block)
each_line.__send__(name, *args, &block)
end
end
次に Ruby1.8 で存在しないメソッドを追加。こっちは Ruby 1.8 で動かすために必要。
unless "".respond_to?('force_encoding')
class String
def force_encoding(encoding)
self
end
end
end
unless "".respond_to?('bytesize')
class String
alias bytesize size
end
end
unless "".respond_to?('ord')
class String
def ord
self[0]
end
end
end
最後に tDiary に特化した変更。
# Ruby1.9でNKF::nkfを呼ぶと文字列のencodingが変わってしまう。
# そのため、encodingがBinaryの環境で動かすと
# "character encodings differ" エラーとなる。
begin
require 'nkf'
module NKF
alias :_nkf :nkf
def nkf(option, src)
r = _nkf(option, src)
r.force_encoding('Binary')
end
module_function :nkf, :_nkf
end
rescue
end
# 日本語を含むツッコミを入れると diary.last_modified が String になる (原因不明)
# (PStore 保存前は Time だが, 保存後に String となる)
# 暫定的に String だったら Time へ変換する
module TDiary
class WikiDiary
def last_modified
if @last_modified.class == String
@last_modified = Time.at(0)
end
@last_modified
end
end
end
index.rb
$defout を $stdout に変更。 $defout は Ruby1.6 との後方互換性のためで、1.8でも非推奨。
Index: index.rb
===================================================================
--- index.rb (revision 97)
+++ index.rb (working copy)
@@ -5,7 +5,7 @@
# Copyright (C) 2001-2006, TADA Tadashi <sho@spc.gr.jp>
# You can redistribute it and/or modify it under GPL2.
#
-BEGIN { $defout.binmode }
+BEGIN { $stdout.binmode }
$KCODE = 'n'
begin
update.rb
index.rb と同じ。
Index: update.rb
===================================================================
--- update.rb (revision 97)
+++ update.rb (working copy)
@@ -5,7 +5,7 @@
# Copyright (C) 2001-2003, TADA Tadashi <sho@spc.gr.jp>
# You can redistribute it and/or modify it under GPL2.
#
-BEGIN { $defout.binmode }
+BEGIN { $stdout.binmode }
$KCODE = 'n'
if pos == 'detail' then
tdiary.rb
ちょこっと変更あり。
- compatible.rb をロード
- instance_variables.each が文字列でなくシンボルを返すように変更になったので to_s で文字列に変換
- eval で宣言したローカル変数が外側で読めないので、 eval 実行時にインスタンス変数への格納まで実施
Index: tdiary.rb
=================================================================== --- tdiary.rb (revision 97)
+++ tdiary.rb (working copy)
@@ -11,6 +11,7 @@
$:.insert( 1, File::dirname( __FILE__ ) + '/misc/lib' )
+require 'compatible'
require 'uri'
begin
@@ -466,6 +467,7 @@
load
instance_variables.each do |v|
+ v = v.to_s
v.sub!( /@/, '' )
instance_eval( <<-SRC
def #{v}
@@ -631,11 +633,10 @@
cgi_conf.untaint unless @secure
def_vars = ""
variables.each do |var| def_vars << "#{var} = nil\n" end
- eval( def_vars )
+ extend_vars = 'variables.each do |var| eval "@#{var} = #{var} if #{var} != nil" end'
Safe::safe( @secure ? 4 : 1 ) do
- eval( cgi_conf, binding, "(TDiary::Config#cgi_conf)", 1 )
+ eval( def_vars + cgi_conf + extend_vars, binding, "(TDiary::Config#cgi_conf)", 1 )
end
- variables.each do |var| eval "@#{var} = #{var} if #{var} != nil" end
rescue IOError, Errno::ENOENT
end
end
misc/lib/hikidoc.rb
String#[] は文字コードではなく文字を返すようになったので、 ord メソッドを呼ぶように変更。 Ruby1.8 環境の場合は compatible.rb で対応している。
Index: misc/lib/hikidoc.rb
===================================================================
--- misc/lib/hikidoc.rb (revision 109)
+++ misc/lib/hikidoc.rb (working copy)
@@ -476,7 +476,7 @@
def escape_meta_char( text )
text.gsub( META_CHAR_RE ) do |s|
- '&#x%x;' % s[1]
+ '&#x%x;' % s[1].ord
end
end
plugin/ja/05referer.rb
前に書いたとおり、エスケープの数の問題。
Index: plugin/ja/05referer.rb
===================================================================
--- plugin/ja/05referer.rb (revision 97)
+++ plugin/ja/05referer.rb (working copy)
@@ -31,7 +31,7 @@
<p>→<a href="#{h @update}?referer=volatile" target="referer">既存設定はこちら</a></p>
<p><textarea name="only_volatile" cols="70" rows="10">#{h @conf.only_volatile2.join( "\n" )}</textarea></p>
<h3 class="subtitle">#{label_referer_table}</h3>
- #{"<p>リンク元リストのURLを、特定の文字列に変換する対応表を指定できます。1件につき、URLと表示文字列を空白で区切って指定します。正規表現が使えるので、URL中に現れた「(〜)」は、置換文字列中で「\\1」のような「\数字」で利用できます。</p>" unless @conf.mobile_agent?}
+ #{"<p>リンク元リストのURLを、特定の文字列に変換する対応表を指定できます。1件につき、URLと表示文字列を空白で区切って指定します。正規表現が使えるので、URL中に現れた「(〜)」は、置換文字列中で「\\\\1」のような「\\数字」で利用できます。</p>" unless @conf.mobile_agent?} き、URLと表示文字列を空白で区切って指定します。正規表現が使えるので、URL中に現れた「(〜)」は、置換文字列中で「\\1」のような「\数字」で利用できます。</p>" unless @con <p><textarea name="referer_table" cols="70" rows="10">#{h @conf.referer_table2.collect{|a|a.join( " " )}.join( "\n" )}</textarea></p>
HTML
amazon.rb
たぶん、rexmlライブラリでエラー - 橋本幸樹のいまさら日記と同じ問題。 とりあえず force_encoding で逃げる。
Index: misc/plugin/amazon.rb
===================================================================
--- misc/plugin/amazon.rb (revision 113)
+++ misc/plugin/amazon.rb (working copy)
@@ -205,6 +205,7 @@
xml = amazon_call_ecs( asin, id_type )
File::open( "#{cache}/#{asin}.xml", 'wb' ) {|f| f.write( xml )}
end
+ xml.force_encoding('UTF-8')
doc = REXML::Document::new( xml ).root
item = doc.elements.to_a( '*/Item' )[0]
if pos == 'detail' then
あとは contrib の category_to_tag.rb も一部変えてる。
追記
移行のときにテストツッコミがRSSに入ったり、RSSがテスト環境にリダイレクトされたりといくつかミスっちゃった。
追記2
自分でやっといてなんだけど、よほどの覚悟がないと Ruby1.9 で動かすのはお勧めしない。 まだまだ 1.9 の非互換な変更が入るかもしれないしね。
追記3
やっぱりまだ不具合がありそう。
- ツッコミが入った日の日記にツッコミフォームが表示されない → hide_comment_form プラグインを無効にすれば表示される
- ツッコミフォームが表示されてもツッコミが反映されない (原因不明)
- ツッコミを入れたら ruby の CPU 使用率が 70% 前後になり、処理が終わらない (強制停止したら makerss でストップ)
たださんからの嬉しいツッコミにお返事できないよ…。なのでここに書く。
ありがとうございます! 熱すぎるかも…と思っていたのですが、UTF8部ランチとマージされる頃にはちょうどいい位に冷めていそうですね。
追記4
ツッコミフォームが表示されない原因が分かった。 今の Ruby1.9 環境だと、ツッコミを入れたときに cache/*.parser に保存されるキャッシュの last_modified が Time でなくて String になってしまうという問題がある。 PStore に保存するときは Time なのに、取り出すときは(読めない) String になる。 原因が分からなかったので、 last_modified が String のときは Time.at(0) にしていたんだけど、この影響で古い日記と判断されてツッコミフォームが消えていた(SPAM対策で古い日記にツッコミできないようにしている)。