Your SlideShare is downloading. ×
  • Like
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

tDiaryなどのレガシーウェブアプリをRuby1.9で動かす方法

  • 3,844 views
Published

 

Published in Art & Photos
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
3,844
On SlideShare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
6
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Open Source Conference 24 Jan. 2009 tDiaryなどの レガシーウェブアプリを Ruby1.9で動かす方法藤岡岳之(xibbar)/(有)ラビックス 日本Rubyの会/Rails勉強会@東北
  • 2. まずご容赦今日発表する4人の中で唯一著作を持っていないことに気がついた大したヤツではありませんm(_ _)mつーか、3人(組)とも著作を持っているなんてすげーよおそらく、よくわからんマニアックな内容をグダグダと話すに違いないtDiaryがまじめに対応しそうなので、セッションのタイトルがピンチ
  • 3. 自己紹介福島市在住秋田県出身福島大学教育学部出身有限会社ラビックス社内では何でも屋もう7年もやってますRuby on Railsでソフト作っています生粋の東北人です
  • 4. ちょっと本業の宣伝中規模向けの携帯連絡網システム販売代理店を募集中収益の一部をRuby財団に寄付します(そんな組織ないけど)
  • 5. Rubyの活動Matz Rubyのコミッタcgi.rbの担当のためだけのコミッタです(現状は)M17N関係のバグ報告はそれなりにしているつもりRails勉強会@東北日本Rubyの会関係に出没
  • 6. 今日は福島か ら来ました
  • 7. 牛タンの ために
  • 8. Ruby会議のため に
  • 9. というわけでアジェンダ第1章 いかに1.9のcgi.rbが腐っていたか第2章 改良した結果、cgi.rbはこうなった第3章 1.9.1のM17Nはこうなった第4章 レガシーアプリはこうやって動かせ
  • 10. 第1章第1章 いかに1.9のcgi.rbが腐っていたか第2章 改良した結果、cgi.rbはこうなった第3章 1.9.1のM17Nはこうなった第4章 レガシーアプリはこうやって動かせ
  • 11. きっかけはReject会議 yuguiさんのセッション
  • 12. 1.9を使ってみてください RejectKaigiでの yuguiさんの布教活動 バグレポートと人柱を 必要としている そろそろ使ってみよう かな
  • 13. Redmineもあるしバグの報告・機能拡張の提案ができるチケットに自動的になるMLに自動的に流れる誰かが担当者に振り、作業することになるcgi.rbだと、担当者が私になります
  • 14. 1.8のcgi.rbみんな使っているRuby on Railsでも使っている一応ちゃんと動く
  • 15. cgi.rbって何ぞや?CGIアプリの開発を支援するライブラリこれがないと、Content-Typeなんとかと自力で出力する羽目になるこれがないと、「id=123&id=456&id=&str=%40h+%3D%7E+%2F%5E%24%2F」こんなのをオレオレunescapeする羽目になるその他、機能いろいろあるけど省略
  • 16. みんなdisっているkwatch cgi.rb がイケてない 12 の理由(るびま)Matz ruby-listとかruby-devにてmput ruby-devあたりでkakutani 札幌Ruby会議にて咳さん 自分のブログで
  • 17. 1.8のcgi.rbはここがダメテストがないマルチパートの時のデータの受け取り方が酷すぎる@cgi[ name ].readみたいなやつ遅い これらは改良したいなぁ
  • 18. 1.9のcgi.rb誰も使っていない積極的メンテナがいない2006年には捨てたいと言われている
  • 19. まだcgi.rbを使いたい既存のアプリがあるcgi.rbのお手軽さもよく知っている世の中の流れはRackに行っているけど、Rackにはないお手軽さもあるよRack => Web Server Gateway Interface
  • 20. cgi.rbでhello world
  • 21. コンソールで実行すると素直でいい子だこの挙動がcgiの基本だと思う
  • 22. そして、1.9で使っ てみる
  • 23. まず、hello worldお、出るじゃん♪
  • 24. 次、日本語単純に日本語にして、実行してみる
  • 25. いつものエラーいつものエラー。こんな時はコンソールだ。
  • 26. コンソールでデバッグこれって、M17Nのエラー気を取り直して、ソースコードのエンコーディングを教えてやるマジックコメントを追加
  • 27. マジックコメントを追加マジックコメントを追加し、ソースのEncodingを教えてやる
  • 28. 例外は回避したけど、肝心の牛タンが表示されていない!
  • 29. 正しくはこうコンソールで見てみよう
  • 30. コンソールでの出力結果fujioka@dhcp155: /cgi-bin% ruby hello_world3.rb </dev/nullContent-Type: text/htmlContent-Length: 79<HEAD><TITLE>Hello World</TITLE></HEAD><BODY>こんにちは、牛タン</BODY>%fujioka@dhcp155: /cgi-bin% ruby19 hello_world3.rb </dev/nullContent-Type: text/htmlContent-Length: 61<HEAD><TITLE>Hello World</TITLE></HEAD><BODY>こんにちは、牛タン</BODY>%予想通り、1.9の方のContent-Lengthの値がおかしい
  • 31. ここまでの感想この程度のことも修正されていないなんて、本当に誰も使っていないんだなcgi.rbは1.9.1のリリース前に削除されてしまうのではないだろうか?こんな動かないライブラリ、ない方がいいでしょ?
  • 32. 早速行動IRCに報告usaさんがfixでも、まともに動かすには大幅なテコ入れが必要だkwatchさんのcgialtを参考に入れ替えたいこっそり、1.8のテストも入れたい
  • 33. テコ入れのステップまず、cgi.rbにテストを導入改造する前にテストを書け by naruseさんでも、これは手間取った1.8とテストは共通では無理cgi.rb本体をファイル分割その他、問題を修正する改善できる機能を改善する
  • 34. 第1章 完
  • 35. 第2章第1章 いかに1.9のcgi.rbが腐っていたか第2章 改良した結果、cgi.rbはこうなった第3章 1.9.1のM17Nはこうなった第4章 レガシーアプリはこうやって動かせ
  • 36. cgi.rbを読んだ感想チャレンジなコードが多い気がするRubyはこんな変な機能があるから使っておけ!みたいな(例えば、継承の方がいいのに、Delegateを使ってみたり)スピードのことは丸っきり考慮がない当時は、スピードが要求される場合はRubyを使ってはいけなかったんだと思う aaa + bbb => aaa << bbb の方が早い
  • 37. 大まかな変更点テストが追加(使う人は関係ないかも)CGI.newするときに受け取るエンコーディングを指定する(デフォルトはUTF-8)CGI.newにブロックを与えて、例外処理を行うことができるマルチパートのデータの受け取りは、IO型ではなくなった救済措置として、readメソッドをくっつけているCGI#outでencodingの変換はしなくなったスピードアップをがんばった
  • 38. テストが追加今後もメンテナンスされていく上で、最も重要なポイントkwatchさんのCGIAltのコードを大分参考にしているCGIというのは標準入力からデータを受け取り、標準出力に出力する 横取りする
  • 39. 横取り方法 標準入力の横取り
  • 40. UTF8なCGIアプリ挙動を実演(hello_world4.rb)
  • 41. EUC-JPなCGIアプリ挙動を実演(hello_world5.rb)
  • 42. Internal Server Error/Users/fujioka/local/lib/ruby19/1.9.1/cgi/core.rb:600:in `block (2 levels) in initialize_query:Accept-Charset encoding error (CGI::InvalidEncoding) from /Users/fujioka/local/lib/ruby19/1.9.1/cgi/core.rb:595:in `each from /Users/fujioka/local/lib/ruby19/1.9.1/cgi/core.rb:595:in `block in initialize_query from /Users/fujioka/local/lib/ruby19/1.9.1/cgi/core.rb:594:in `each from /Users/fujioka/local/lib/ruby19/1.9.1/cgi/core.rb:594:in `initialize_query from /Users/fujioka/local/lib/ruby19/1.9.1/cgi/core.rb:752:in `initialize from hello_world5.rb:4:in `new from hello_world5.rb:4:in `<main> 受け取るデータのencoding error
  • 43. encodingを指定する hello_world6.rb 受け取るencodingを指定する必要がある オプションはHashで指定するようにした
  • 44. 例外じゃいやだencodingの例外を入れておく器 encodingの例外を入れる処理を ブロックで渡してしまう encodingをチェックし、 変換できそうだったら変換 hello_world7.rb
  • 45. 面倒になった気もするが、
  • 46. UTF-8で書いておけ
  • 47. multipart form on 1.8 hello_world8.rb受け取ったデータはIO型であることに注目この仕様はひどすぎると思う
  • 48. multipart form on 1.9 ある程度、互換性は保ちたい でも、この酷い仕様はやめてStringにするそーだ、String型にselfを返す readを特異メソッドで くっつけてしまおうdefine_method(:read){self}
  • 49. 受取データはString hello_world9.rbStringになったので、これだけでOK
  • 50. CGI#filesでファイル一覧 hello_world10.rbCGI#filesでHash形式でアップロードされたファイルを一式取得できる
  • 51. 好き放題やっているcgi.rbはコミッタの間で利用者が少ない特に、タグ生成メソッドあたりは好き放題できるライバルはhamlだと思っているRSSの配信なんかもcgi.rbでささっと出力するのが楽だと思うもっと早くしたいもっとよくしたい(会社が暇な時期に)
  • 52. 第2章 完
  • 53. 第3章第1章 いかに1.9のcgi.rbが腐っていたか第2章 改良した結果、cgi.rbはこうなった第3章 1.9.1のM17Nはこうなった第4章 レガシーアプリはこうやって動かせ
  • 54. 文字数をカウントする 1.8の時代"牛タン".split(//u).size=> 3 1.9の時代irb> "牛タン".size=> 3irb> "牛タン".bytesize=> 9 Rubyは真の国際言語へ!
  • 55. 重要なこと StringのインスタンスがEncoding情報を持つようになった RubyのM17Nの大前提ですirb(main):001:0> "ほげ"=> "ほげ"irb(main):002:0> "ほげ".encoding=> #<Encoding:UTF-8>
  • 56. 1.9のString型 Encoding情報を持つようになったString#encoding # 現在のEncodingString#force_encoding(encoding) # エンコーディングを強制変更String#encode(encoding) # 文字列をエンコードString#valide_encoding? # エンコーディングがあっているかチェックString#ascii_only? # 7bit ASCIIのみかどうかチェック
  • 57. EncodingクラスEncoding.list # 有効なEncoding一覧Encoding.find(encoding) # encodingが有効かどうか調べるEncoding.default_external # デフォルト外部エンコーディングEncoding.default_internal # デフォルト内部エンコーディング(xibbarは説明できない) デフォルトエンコーディングは代入できるのだが、あまり しない方がいいと思う
  • 58. Encodingの種類US-ASCII # ABab123などの7bit ASCII文字列ASCII-8BIT # バイナリだと思ってOKUTF-8、EUC-JP、SJISなど(説明省略)
  • 59. 外部Encodingirb> Encoding.default_external=> #<Encoding:UTF-8>irb> open(/tmp/hoge.rb,r:euc-jp).read.encoding=> #<Encoding:EUC-JP>irb> open(/tmp/hoge.rb,r).read.encoding=> #<Encoding:UTF-8> Encoding.default_externalのこと 1.9ではファイルをオープンする時に Encoding情報を与える 省略された場合は Encoding.default_externalが採用される
  • 60. 外部Encodingをキメる% ruby19 -Eeuc-jp sample.rb#!/usr/bin/ruby19 -Eeuc-jp #<=shebang行Encoding.default_external= コマンドラインで与える shebang行で指定する 代入する(非推奨だと思う) 環境変数(LANGとか)
  • 61. String#encodeirb> "ほげ"=> "ほげ"irb> "ほげ".encoding=> #<Encoding:UTF-8>irb> "ほげ".encode("EUC-jp")=> "?‫"?ۿ‬ 文字列をencodeする 破壊的に変換するので注意
  • 62. String#force_encodingirb> "ほげ".force_encoding("EUC-JP")=> "xE3x81??x81x92"irb> "ほげ".force_encoding("ASCII-8BIT")=> "xE3x81xBBxE3x81x92"irb> "ほげ".force_encoding("US-ASCII")=> "xE3x81xBBxE3x81x92" Encoding情報を強制変換 破壊的に変換するので注意 バイト列自体は変化しない 間違ったEncoding情報の文字列を生成できる
  • 63. String#valid_encoding?irb> "牛タン".valid_encoding?=> trueirb> "牛タン".force_encoding("EUC-JP").valid_encoding?=> false Encoding情報が正しいかをチェックする
  • 64. 合体 その1irb> "ほげ"+"ふが"=> "ほげふが"irb>"ほげ"+"ふが".force_encoding("US-ASCII")Encoding::CompatibilityError: incompatiblecharacter encodings: UTF-8 and US-ASCII> "abc"+"ふが".force_encoding("ASCII-8BIT")=> "abcxE3x81xB5xE3x81x8C" 同じEncoding同士は連結できる 基本的に違うEncodingは連結できない ただし、7bit ASCIIしかない場合は連結できる
  • 65. 合体 その2irb> ("abc".force_encoding("ASCII-8BIT")+"def").encoding=> #<Encoding:UTF-8>irb> ("abc".force_encoding("US-ASCII")+"def").encoding=> #<Encoding:US-ASCII> 7bit ASCIIしかないASCII-8BITは連結できる Encoding情報は柔軟に判断される 下の挙動はバグだとさ(発見してしまった)
  • 66. 文字列dumpirb> "ほげfuga".dump=> ""u{307b}u{3052}fuga""irb> "ほげfuga".inspect=> ""ほげfuga""irb> Marshal.dump("ほげfuga")=> "x04bI"x0FxE3x81xBBxE3x81x92fugax06:rencoding"nUTF-8" 上2つはただのバイト列で、Scriptの Encodingに依存する Marshal.dumpはEncoding情報がつく
  • 67. マジックコメントソースコードのエンコーディングを明示するこれがないとRubyはソースに埋め込んである文字列のencodingがわからない1.8の時はバイト列扱いだった2種類あるemacs方式(# -*- coding: utf-8 -*-)vim方式(# vim:fileencoding=UTF-8)
  • 68. まとめStringは常にEncoding情報を持っていることを意識しようStringをファイルなりDBなりに保存するときは、データを保存したいのか、Encodingごと保存したいのかを考えよう日本語を含む場合はマジコメ(マジックコメント)を忘れずにつけよう
  • 69. 第3章 完
  • 70. 第3章第1章 いかに1.9のcgi.rbが腐っていたか第2章 改良した結果、cgi.rbはこうなった第3章 1.9.1のM17Nはこうなった第4章 レガシーアプリはこうやって動かせ
  • 71. Open Source Conference 24 Jan. 2009 tDiaryなどの レガシーウェブアプリを Ruby1.9で動かす方法藤岡岳之(xibbar)/(有)ラビックス 日本Rubyの会/Rails勉強会@東北
  • 72. tDiaryが1.9に対応 しそうだ
  • 73. あっさり 転身
  • 74. Open Source Conference 24 Jan. 2009 tDiary Hikiなどの レガシーウェブアプリを Ruby1.9で動かす方法藤岡岳之(xibbar)/(有)ラビックス 日本Rubyの会/Rails勉強会@東北
  • 75. Hikiとは?Before Rails世代のwikiRubyだけで動く
  • 76. とりあえず1.8で動かすsvn co むにゃむにゃしhikiのためにとりあえずwebrick serverを用意hikiconf.rb.sampleをhikiconf.rbにコピーdataフォルダとcgiファイル名だけ設定
  • 77. 1.8ではあっさり起動1.8.6で起動している
  • 78. 1.9ではどうかというと日本語が入ったソースはマジックコメント必要
  • 79. というわけで追加--- hikiconf.rb.sample 2009-01-19 16:56:34.000000000 +0900+++ hikiconf.rb 2009-01-22 13:39:06.000000000 +0900@@ -1,3 +1,4 @@+# -*- coding: euc-jp -*- # $Id: hikiconf.rb.sample,v 1.20 2006-07-31 13:43:20 fdiary Exp $ # Copyright (C) 2002-2003 TAKEUCHI Hitoshi <hitoshi@namaraii.com> 1行目にマジックコメントを追加する
  • 80.
  • 81. 同じ類いのエラーちょいちょいとマジコメをつける
  • 82. エラーが出な くなるまで マジコメる
  • 83. 別のエラーが出たEUC-JPとASCII-8BITは合体できません
  • 84. 外部encodingを変更Encoding.default_externalのことIO型を開いたときに、読み込んだデータのencodingのデフォルト値 ruby -Eeuc-jp sample.rbとオプションを渡す #!/usr/bin/ruby -Eeuc-jp とshebangで指定 Encoding.default_external= で指定これをつけると、open( hoge ).readが自動的にEUC-JPになる
  • 85. WEBRickの設定を変更 rubybin = "#{ENV[HOME]}/local/bin/ruby19"rubybin = "#{ENV[HOME]}/local/bin/ruby19 -Eeuc-jp" hikiserver.rbで外部encodingを指定
  • 86. 表示されたこれだけで表示だけはされた
  • 87. 表示はできるようだ1.8で作成し、1.9での表示まではOK
  • 88. 新規ページを作ってみる新規ボタンを押すと、、、
  • 89. 予定通りエラーEUC-JPなんだから、CGI.newするときに受信するencodingを教えてあげるCGI::newでinitializeしてた。grepかけても見つからない訳だ。。。
  • 90. ページの作成こんなエラーが出た
  • 91. 探ってみると、hiki/db/tmarshal.rb の中を見ると Array#to_sを使って いる
  • 92. Array#to_sが違う% ruby -e puts ["aaanbbb","cccnddd"].to_saaabbbcccddd% ruby19 -e puts ["aaanbbb","cccnddd"].to_s["aaanbbb", "cccnddd"] map/collectした結果をto_sとかやらない ように Array#joinを使うこと
  • 93. PStoreの独自拡張undefined method `commit_new for #<PTStore:0x40bcbc>Please back to FrontPage. Hikiはpstoreを独自拡張して、オレオレ transactionを作成している PTstore#transactionを丸ごとコメントし て無効にしてやったら動いた
  • 94. ひととおり動くようにwikiのページの閲覧、作成ができた
  • 95. まとめマジコメ(マジックコメント)をつけるEncoding.default_externalを指定するUTF-8以外の時は、CGI.newする時に:accept_charsetを指定するそれ以外は地道につぶす String#eachとか?
  • 96. 第4章 完
  • 97. 全体的なまとめcgi.rbも一応動くようにはなっているM17Nでハマらないように