よたらぼ
自分の興味の赴くままにIT技術系のネタを取りとめもなくメモっています。
Ruby言語やLinuxのネタが多いです。

February 26, 2009 [おもひで]

[Rails] Rack-0.9.1を試す

早くもlocale_railsがRails-2.3.0rc1で動作しなくなった。

Rack統合が原因であることはすぐにわかった(ActionController::AbstractRequestがなくなったことでエラーになっていた)が、そもそもRackって何ぞや、ということで試してみることにした。

こちらを参考に。

まずはインストール

gem install rack

hello.rb

 require 'rubygems'
 require 'rack'
 
 class HelloApp
   def call(env)
     body = "Hello, Rack"
     [200, {"Content-Type" => "text/plain"}, [body]]
   end
 end

hello.ru

 require 'hello'
 run HelloApp.new

サーバ起動

 $ rackup hello.ru

Firefoxからhttp://localhost:9292/ にアクセスして・・・ NO!! ほぼコピペなのにエラー・・・orz。

Rack::Lint::LintError: No Content-Length header found

このバージョンではContent-Lengthを指定しないといけないのか・・・。なるほど。

 require 'rubygems'
 require 'rack'
 
 class HelloApp
   def call(env)
     body = "Hello, Rack"
     [200, {"Content-Type" => "text/plain", "Content-Length" => body.length}, [body]]
   end
 end

サーバ再起動。うーん、またしてもエラー。

Rack::Lint::LintError: header values must respond to #each, but the value of 'Content-Length' doesn't (is Fixnum)

#each持ってないといけないのか・・・・。Fixnumじゃダメってことなのね。とりあえず配列にしてみよう。

 require 'rubygems'
 require 'rack'
 
 class HelloApp
   def call(env)
     body = "Hello, Rack"
     [200, {"Content-Type" => "text/plain", "Content-Length" => [body.length]}, [body]]
   end
 end

サーバ再起動。うーん、またしてもエラー。

Rack::Lint::LintError: header values must consist of Strings, but 'Content-Length' also contains a Fixnum

文字列じゃないとダメってことか?

 require 'rubygems'
 require 'rack'
 
 class HelloApp
   def call(env)
     body = "Hello, Rack"
     [200, {"Content-Type" => "text/plain", "Content-Length" => body.length.to_s}, [body]]
   end
 end

"Hello, Rack" やったーっ!(ヒーローズのヒロ風。勢いで牡丹をジンタンと読む感じで)

.... ってか、疲れた。locale_railsはまた後にしよう。

[Rails] Rack-0.9.1 + Ruby-Locale-0.9.0

LocaleのCGIドライバは、Ruby標準添付のCGIモジュールに依存した作りになっているのだが、CGIを使わずにRack::Requestを使用するRackではそのままではRuby-Localeを使えない。で、ちょっとだけRack::RequestをいじってCGIと同じように振る舞うようにしてしまうことでRuby-Localeで動作するようになる。

 require 'rubygems'
 require 'rack'
 require 'locale'
 
 module Rack
   class Request
     def has_key?(key); params.has_key?(key); end
     def accept_language; env["HTTP_ACCEPT_LANGUAGE"]; end
     def accept_charset; env["HTTP_ACCEPT_CHARSET"]; end
  end
 end
 
 class HelloApp
   Locale.init(:driver => :cgi)
 
   def call(env)
     request = Rack::Request.new(env)
     Locale.set_cgi(request)
     str = "#{Locale.candidates.inspect}"
     [200, {"Content-Type" => "text/plain", "Content-Length" => str.length.to_s}, [str]]
   end
 end

ちなみにRails-2.3.0の新しいActionController::RequestはRack::Requestを継承しつつ、CGIに近いインタフェースになっているのでLocaleのCGIドライバをそのまま使える・・・といいのだけど・・・。has_key?は無さげだ・・・orz。


編集