Slow Dance RSSフィード

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」とかを使って解析するってのもいいなー。色々改良点がある。