2008-06-28
Gem のバージョンあげたら大変な目にあった
知りませんでした。Gem って、yum とかと同じで、パッケージ管理をするものだと思ってました。今回、Gem のアップデートがあったということで、以下のように「0.9.4」から「1.2.0」にアップデートしたら、「RMagick 1.13.0」が動かなくなった。
最初に、gem をアップデートした。
$ gem update --system
しばらくして、作っているアプリケーションのテストを通してみると。
Started
E........
Finished in 0.547 seconds.
1) Error:
test_create_image?(PhotoTest):
NoMethodError: undefined method `resize_to_fit' for #<Magick::Image:0x47d4b4c>
C:/RailsS/rixi/trunk/config/../app/models/photo.rb:212:in `image_resize'
C:/RailsS/rixi/trunk/config/../app/models/photo.rb:196:in `create_image?'
photo_test.rb:135:in `test_create_image?'
む。なんかRMagick 関連で全てこける。「resize_to_fit」が定義されてないとのこと。でも、ソース見るとメソッドあるし。なんでだ。
ためしに、irbでやってみる。
$ irb -r 'RMagick' > i = Magick::Image.new(10, 10) { self.background_color = 'black' } > i.resize_to_fit > NoMethodError: undefined method `resize_to_fit' for #<Magick::Image:0x53a6b4c>
やはりだめだ。なんでか調べてみると、gem のupdate が問題だった。
中のREADME.htmlでも脅されてますが、ImageMagickとRMagickのバージョンはダウンロードしてきたファイル内のものと必ず合わせること、とあります。
gemのバージョンが違うだけでもさっぱり動かないので、おとなしく従っといたほうが利口のようです。
パッケージによってはgem のバージョンに依存してるものもあるんですね。
しかたがないので、gem のバージョンを戻すことを試みる。
む。gem のダウングレードの仕方が分からん。gem って「--version」みたいにバージョンを指定してインストールとかできんのか。「アーカイブ」から「rubygems-update-0.9.4.gem」をもってきて「gem install」してもだめ。update を使ってダウングレードは無理か。
なので、gem自体を入れ直そうとしたら失敗。現在のをアンインストールする前に入れてしまい何がなんだか分からなくなり、ruby ごと再インストール。
gem は「0.9.4」に戻した。
ガーン。何故かまた同じ原因でテストこける。なんなんだ。
これを調べたら、ruby 自体のバージョンも関係していた。以前は「ruby 1.8.6 25(patch level 0) mswin」のFinal Release を使っていたが、再インストールした際には「ruby 1.8.6 26(patch level 111) mswin」のFinal Release 版を入れたため。「ruby 1.8.6 25」版を入れたら動いた。
RMagickのドキュメントには以下のように書いてあるが、うそっぱち。
gem - -version should yield 0.9.0 or higher. Just do that gem update - -system once in a while.
higherで動く保証はない。
「Magick 1.13.0」は「ruby 1.8.6 25 mswin」、「rubygems 0.9.4(2でもいけた)」というかなり制限されたでないと動かない。
Twitterに投稿するスクリプト
APIをさわったことがないので、練習にさわってみました。練習台はTwitter。
APIの仕様
- 認証
認証
public_timeline の取得を除くすべての API で、BASIC認証を使用する。BASIC認証で使用するユーザ名はメールアドレスになる。
(訳者による注記: 現在は、スクリーン名も使える)
- 投稿
update
自分のステータスを更新(update)する。引数 status は必須。
この API は必ず POST を使って発行すること。update が成功した場合は、format で指定した形式で応答が返る
URL: http://twitter.com/statuses/update.format
(format は xml, json のうちのいずれかを指定)
引数:
status=ステータス (必須)
ステータス(発言、投稿内容)を指定する。必ず URL エンコードすること。
ステータスは 160バイト以内におさめること。ただし、140バイトを超えた部分は必ずしも表示される保証はない。
おぉ。シンプルですね。そもそも、APIはリクエスト送って、それに対して結果がXMLとかJSONとかで返ってくるってだけだもんな。APIって言葉に難しさを感じていた気がする。実際は超シンプル。
投稿スクリプト
- twitter_api.rb
require 'base64' require 'net/http' require 'nkf' require 'uri' Net::HTTP.version_1_2 ADDRESS = 'your mailaddress' PASSWORD = 'your password' BASE_URI = 'twitter.com' def url_encode(params) encoded = params.keys.inject({}){|h, k| h.merge(k => URI.encode(params[k]))} encoded.keys.zip(params.values).map{|i| i.join('=')}.join('&') end def call(api, params = {}) res = nil Net::HTTP.start(BASE_URI) do |http| res = http.post( "/#{api}.xml", url_encode(params), {"Authorization" => "Basic " + Base64.encode64("#{ADDRESS}:#{PASSWORD}")} ) end case res when Net::HTTPOK res.body else raise "API Error" end end def post(message) begin call('statuses/update', "status" => NKF.nkf("-w", message)) p "Posted" rescue p "Posted unsuccessfully" end end if message = ARGV[0..-1].join('') post(message) end
- 使い方
$ ruby twitter_api.rb メッセージ
url_encodeが汚くなった。Net::HTTP::Post使えばこんな風に書けるな。今回は、Basic認証も学びたかったので直書きした。
def post(message) req = Net::HTTP::Post.new('/statuses/update.xml') req.basic_auth(ADDRESS, PASSWORD) req.set_form_data("status" => to_utf8(message)) Net::HTTP.start(BASE_URI) do |http| res = http.request(req) end end
あと、エラーをpost メソッドでキャッチしてるのが微妙。これだと、API増えるたびにエラーを補足する羽目になるな。レスポンスを「rexml/document」とかを使って解析するってのもいいなー。色々改良点がある。
