/ 最近 .rdf 追記 編集 設定 本棚

log[20090223]報・ruby-1.9.1不思議で困ったことが起こった



20090223()

[Ruby][tDiary]ruby-1.9.1不思議で困ったことが起こった

問題のコ(再掲)はこれあるハッシュのキーについて繰り返しているのにッシュにそのキーが存在しない(すべてのキーが見つからないわけではないが見つからないキーはいつでも見つからな)

categorized.keys.each do |c|
	PStore.new(cache_file(c)).transaction do |db|
		categorized.fetch(c) #=> key not found (KeyError)
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

fetchをブロックの最初に持って行くとそこではエラーにならない

categorized.keys.each do |c|
		categorized.fetch(c) #=> O.K.
	PStore.new(cache_file(c)).transaction do |db|
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

cache_file(c)の呼び出しが原因その中でも includeしてある ERB::Utilu()メソドが核心

categorized.keys.each do |c|
		::ERB::Util.u(c)
		categorized.fetch(c) #=> key not found (KeyError)
	PStore.new(cache_file(c)).transaction do |db|
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

引数にした文字列のエンコングが変わってしまっている

categorized.keys.each do |c|
		enc1 = c.encoding;
		::ERB::Util.u(c)
		enc2 = c.encoding
		categorized.fetch(c) { raise "#{enc1} #{enc2} #{::ERB.version}" } #=> UTF-8 ASCII-8BIT erb.rb [2.1.0 2009-01-11] (RuntimeError)
	PStore.new(cache_file(c)).transaction do |db|
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

ERB::Util.url_encodeの定義を見ると引数の文字列を dupした後にエンコングを変更しているにも関わらず呼び出し元に影響を与えてしまっている

    def url_encode(s)
      s.to_s.dup.force_encoding("ASCII-8BIT").gsub(/[^a-zA-Z0-9_\-.]/n) {
        sprintf("%%%02X", $&.unpack("C")[0])
      }
    end
    alias u url_encode

そんなわけだから呼び出し側(category.rb)

u( c.dup )

なんてやっても効果はなく

u( ""+c )

あるいは

u( "#{c}" )

とやって初めて今回の現象を回避することができた

これは、文字列の複製を遅らせた結果期せずしておこった現象にみえる

バグのはずなんだけどirbで再現しようと思ってもできないんだこれ


 追記@2009-08-13: 見る人が見れば修正はあっという間でした

http://redmine.ruby-lang.org/issues/show/1929

(ここに見るべき場所を見つけることもできなかった人間がひと)

* 正しくは ruby-1.9.2dev(2009-02-03)