GAE/JRuby/Sinatra でサービスを作ってみるテスト (2)
くっそー、ハマった。
タダだべを GAE に移植するには、要するに「メールで遠隔操作するブラウザ」を作ればいいわけで、Ruby Mechanize を GAE 上で動かすとこまでは OK*1。セッションをまたいでリンクをたどるためには履歴と付加情報 (リファラとかクッキーとか) が必要なので、いっそ Mechanize オブジェクトを丸ごとデータストアに突っ込んで再利用してやろうと…
require "mechanize" require "dm-core" class BrowserData include DataMapper::Resource property :id, Serial property :username, String, :required => true, :unique => true property :agent, Object, :required => true end class Browser def initialize(username) @username = username @browserdata = BrowserData.first_or_create( { :username => username }, { :agent => WWW::Mechanize.new } ) @agent = @browserdata.agent end end
…したら…
TypeError - can't dump hash with default proc: file:/home/www/appengine1@gae/toybox3/WEB-INF/lib/gems.jar!/bundler_gems/jruby/1.8/gems/dm-core-1.0.2/lib/dm-core/property/object.rb:13:in `dump' (中略) file:/home/www/appengine1@gae/toybox3/WEB-INF/lib/gems.jar!/bundler_gems/jruby/1.8/gems/dm-core-1.0.2/lib/dm-core/model.rb:446:in `first_or_create' /home/www/appengine1@gae/toybox3/models/browser.rb:19:in `initialize'
…えっ? も、もしや…
デフォルトオブジェクトが Proc である Hash は dump できない
h = Hash.new { } Marshal.dump(h) => -:2:in `dump': cannot dump hash with default proc (TypeError)http://www.ruby-lang.org/ja/man/html/Marshal_A5D5A5A9A1BCA5DEA5C3A5C8.html
ナンダッテー (´Д`;
ちょっと調べたところ、怪しいのは www/mechanize.rb の 139 行目。
@scheme_handlers = Hash.new { |h,k| h[k] = lambda { |link, page| raise UnsupportedSchemeError.new(k) } } @scheme_handlers['http'] = lambda { |link, page| link } @scheme_handlers['https'] = @scheme_handlers['http'] @scheme_handlers['relative'] = @scheme_handlers['http'] @scheme_handlers['file'] = @scheme_handlers['http']
ここ 1 か所だけなんだがな―。直してオレオレ gem を作ればいけるのか?
とりあえずフォークしてみた。けど、それからどうすりゃいいんだ?
同日追記
とりあえずローカルで直してみた。@scheme_handlers は事実上いらないのでさっぱり消した。生成したばかりの Mechanize オブジェクトはシリアライズできるようになった。しかし一度アクセスするとソケットが開きっぱなしになるらしく、ソケットはシリアライズできないので、やっぱりだめぽ。…いちいちソケットを閉じて破棄するようにするか??
*1:Mechanize は Nokogiri に依存しない旧版 0.8.5 を利用