わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

Ruby/(A)AWSからiconvを除去する

## Ruby 2.0.0 とは?
Ruby 2.0.0 は Ruby 2.0 系列の最初の安定版リリースです。

おめでとうございます.これからも使っていきます.
だけど…

### 非互換について
特筆すべき非互換を 5 つ把握しています。
(略)

  • iconv が削除されました。元々 M17N が導入された 1.9 の時点で非推奨のものでした。String#encode などを使って書き換えてください。

これは要注意です.以前に,Ruby/AWSで商品検索を書き,このコードはhatedmaの一部として,今も,ISBNから書籍の詳細を知るのに,活用しています.
Ruby 2.0.0devの時点から,iconvが利用できなくなっていて,aws.rbを書き換えていました.
ここに,iconvに起因するエラーの発生と,その除去の手順を取りまとめておきます.
とはいうものの,「除去しない」方法のほうがスマートです.具体的には,「gem install iconv」を実行します.Rubyist Magazineで知りました.

0. 前提

以下を前提とします.

  • ソースからRubyをビルドできます(makeなどのコマンドが使用可能となっています).
  • ~/.amazonrcの設定をしています.

Ubuntu 12.10で動作確認を行いました.

1. Ruby 2.0.0-p0のビルドとインストール

$ cd ~/src
$ wget ftp://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p0.tar.bz2
$ tar xf ruby-2.0.0-p0.tar.bz2
$ cd ruby-2.0.0-p0
$ ./configure --prefix=$HOME/Lib/ruby200p0 --enable-shared --enable-pthread
$ make
$ make install
$ cd ..
$ PATH=$HOME/Lib/ruby200p0/bin:$PATH
$ ruby -v
ruby 2.0.0p0 (2013-02-24) [x86_64-linux]

2. Ruby/(A)AWSのインストール

$ gem install ruby-aaws
$ gem list

*** LOCAL GEMS ***

bigdecimal (1.2.0)
io-console (0.4.2)
json (1.7.7)
minitest (4.3.2)
psych (2.0.0)
rake (0.9.6)
rdoc (4.0.0)
ruby-aaws (0.7.0)
test-unit (2.0.0.0)

ちなみにhttp://rubyforge.org/frs/?group_id=6508&release_id=43077を見ると最新バージョンは0.8.1です.上のとおりインストールした0.7.0で,話を続けます.

3. iconvのせいで失敗

$ wget https://gist.github.com/takehiko/1579329/raw/amazon-searcher.rb
$ ruby amazon-searcher.rb 4006000812
(略)/Lib/ruby200p0/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:
45:in `require': cannot load such file -- iconv (LoadError)
        from (略)/Lib/ruby200p0/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'
        from (略)/Lib/ruby200p0/lib/ruby/gems/2.0.0/gems/ruby-aaws-0.7.0/lib/amazon/aws.rb:12:in `<module:AWS>'
        from (略)/Lib/ruby200p0/lib/ruby/gems/2.0.0/gems/ruby-aaws-0.7.0/lib/amazon/aws.rb:7:in `<module:Amazon>'
        from (略)/Lib/ruby200p0/lib/ruby/gems/2.0.0/gems/ruby-aaws-0.7.0/lib/amazon/aws.rb:5:in `<top (required)>'
        from (略)/Lib/ruby200p0/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'
        from (略)/Lib/ruby200p0/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'
        from (略)/Lib/ruby200p0/lib/ruby/gems/2.0.0/gems/ruby-aaws-0.7.0/lib/amazon/aws/search.rb:8:in `<module:AWS>'
        from (略)/Lib/ruby200p0/lib/ruby/gems/2.0.0/gems/ruby-aaws-0.7.0/lib/amazon/aws/search.rb:6:in `<module:Amazon>'
        from (略)/Lib/ruby200p0/lib/ruby/gems/2.0.0/gems/ruby-aaws-0.7.0/lib/amazon/aws/search.rb:4:in `<top (required)>'
        from (略)/Lib/ruby200p0/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:110:in `require'
        from (略)/Lib/ruby200p0/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:110:in `rescue in require'
        from (略)/Lib/ruby200p0/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:35:in `require'
        from amazon-searcher.rb:9:in `<main>'

もし,wgetコマンドを実行したときに「エラー: `gist.github.com' の証明書の発行者が不明です。」で終わり,ファイルが取得できなかった*1ときは,wgetに--no-check-certificateオプションをつけて実行し直せば,取得できるようになります.
いろいろとファイル名が表示されたのですが,修正すべきなのはaws.rbのみです.

4. iconvの処理を取り除けば成功

$ pushd $HOME/Lib/ruby200p0/lib/ruby/gems/2.0.0/gems/ruby-aaws-0.7.0/lib/amazon
$ wget https://gist.github.com/takehiko/5023480/raw/aws.rb.diff
$ patch < aws.rb.diff
$ popd
$ ruby amazon-searcher.rb 4006000812
author: 高木 貞治
binding: 文庫
ean: 9784006000813
ean_list:
        ean_list_element = 9784006000813
isbn: 4006000812
label: 岩波書店
list_price:
        amount = 945
        currency_code = JPY
        formatted_price = ¥ 945
manufacturer: 岩波書店
number_ofpages: 190
package_dimensions:
        height = 47
        length = 583
        weight = 31
        width = 417
product_group: Book
product_type_name: ABIS_BOOK
publication_date: 2002-04-16
publisher: 岩波書店
sku: MO_110926-0016
studio: 岩波書店
title: 数学小景 (岩波現代文庫)
asin: 4006000812

[asin:4006000812]
http://www.amazon.co.jp/dp/4006000812

うまくいきました.

5. iconv除去の基本方針

library iconvによると,Iconvのコンストラクタや主要なクラスメソッドは,最初の引数が変換後,2番目の引数が変換対象(変換前)の文字コードとなります.
この点に注意して,今回のaws.rb(オリジナル)を見ていくと,中に「Iconv.new( 'utf-8', encoding )」という式があります.encodingをUTF-8に変換するというものです.
すなわち,もとの文字列が何でエンコードされていようと,それをUTF-8に変換するという処理をしているのでした.それに気づくと話は簡単で,変換のためのIconvインスタンスを作らないようにし,実際に変換をしている箇所では,「v.to_s.toutf8」としました.String#toutf8を利用するために,kconvを使用しました.
UTF-8から他の文字コードに変換する場合,次のようにすればよさそうです.

  • Ruby 1.8/1.9/2.0対応にするには:
    • 「require "iconv"」は,「require "kconv"」に置き換えます.
    • 「Iconv.new("sjis", "utf-8").iconv(str)」は,「str.tosjis」に置き換えます.
    • 「Iconv.new("iso-2022-jp", "utf-8").iconv(str)」は,「str.tojis」に置き換えます.
    • 「Iconv.new("euc-jp", "utf-8").iconv(str)」は,「str.toeuc」に置き換えます.
  • Ruby 1.9/2.0対応で良ければ:
    • 「require "iconv"」は,取り除きます.
    • 「Iconv.new("sjis", "utf-8").iconv(str)」は,「str.encode("sjis")」に置き換えます.
    • 「Iconv.new("iso-2022-jp", "utf-8").iconv(str)」は,「str.encode("iso-2022-jp")」に置き換えます.("jis"では失敗しました.)
    • 「Iconv.new("euc-jp", "utf-8").iconv(str)」は,「str.encode("euc-jp")」に置き換えます.("euc"では失敗しました."eucjp"はOKでした.)

6. バージョン0.8.1用

Cygwinで動作確認をしていったところ,gem install ruby-aawsでインストールされたバージョンが0.8.1となりました.
aws.rbの修正箇所も同様,と言いたいところですが,行番号が変わっています.
そこで0.7.0とは別に,パッチをGistで公開しました.適用には,次のコマンドを実行してください.

$ cd $HOME/Lib/ruby200p0/lib/ruby/gems/2.0.0/gems/ruby-aaws-0.8.1/lib/amazon
$ https://gist.github.com/takehiko/5023820/raw/aws.rb.patch
$ patch < aws.rb.patch

2つのGistのURLは以下のとおりです.

(最終更新:2013-02-24 深夜)

*1:Ubuntuでは発生せず,Cygwin環境で発生しました.