BLOGTIMES
» ArchiveList (Tag for "ruby" )
«Prev || ... 2 · 3 · 4 · 5 · 6 · 7 · 8 · 9 · 10 ·... | | Next»
2011/01/27

下位クラスで再定義された定数を上位クラスで使う

ruby 

ちょっと前に書いたRubyスクリプトの定数部分だけを書き換えたクラスが必要になったのですが、コピーして定数部分を書き換えて使うのはださすぎるし、なるべくスーパークラスの修正は少なくしたいし、ということで何かいい方法がないかと思って試行錯誤してみたらいい方法を思いついたのでメモ。

具体的にはCONSTと書くところをself.class::CONSTとすることで上位クラスで定義されたメソッドであっても、下位クラスで定義された定数を使って動いてくれます

class A CONST = 'aaa' def put_const() puts CONST + ',' + self.class::CONST end end class B < A CONST = 'bbb' end class C < B end A.new.put_const # => aaa,aaa B.new.put_const # => aaa,bbb C.new.put_const # => aaa,bbb

本当はちゃんとリファクタリングすべきですが、今回は急ぎなのでひとまずこれでよしとしました。
ファイルをコピーして使うよりも幾分ましでしょう。


    at 19:08 |
    2011/01/13

    JRuby 1.6はOLEがサポートされるらしい

    ruby 

    JRuby 1.6がまもなくリリースされるようです。

    JRuby最新版はRuby 1.9.2対応とC拡張導入、OLEにも対応 | エンタープライズ | マイコミジャーナル

    JRubyの最新版となるJRuby 1.6のリリースが迫ってきた。13日現在、JRuby 1.6 RC1が公開されており、ユーザからのフィードバックを得て最終的に仕上げてから正式リリースとなる見通し。JRuby 1.6はこれまでのJRubyリリースの中でもっとも大きなリリースになると説明されており、開発の進捗に自信が伺える。

    上記の記事にOLEにも対応という話が気になったので、ちょっと調べてみたのですが、[ANN] JRuby 1.6.0.RC1 releasedを読む限りでは、以前使ったjruby-win32oleがバンドルされるだけのようです。ひとまずRCが取れるまで待って、正式版になったらいろいろ試してみよう。


      at 22:50 |
      2010/11/29

      UTF-8のBOMの削除でハマる

      java  ruby  charset  regex 

      XalanでXMLをXSL変換するプログラムを書いたら、そのうちの1つのXMLが下記のエラーを吐いて変換できなくてハマってしまいました。

      Caused by: javax.xml.transform.TransformerException: com.sun.org.apache.xml.internal.utils.WrappedRuntimeException: An invalid XML character (Unicode: 0xfffe) was found in the element content of the document.

      エラーから分かることはドキュメントに0xFFFEが含まれているということ。この文字はBOM(0xFEFF)のエンディアンを間違えたときの文字列なので確かにXMLに使うことはできません。エディタで開くと一見間違いはないように見えますが、Firefoxで表示させようとすると「XML パースエラー: 整形式になっていません。」と他の処理系でもエラーを吐きます。

      元になったXMLはRubyのプログラムから生成したものだったので、元になったStringから下記のように BOM を削除するルーチンを埋め込んでみました。

      str = str.gsub(/\xFE\xFF|\xFF\xFE/,"")

      上記を利用してXMLを再生成してみたのですが、依然としてエラーは消えません。ここでしばらくハマっていましたが、XalanはJavaなので0xFFFEはUTF-16の表現であることを見落としていることに気づきました。今回のXMLはUTF-8だったので、BOMのUTF-8表現を「日本語文字コード変換 mojimoji」で調べて正規表現を書き直したところ、これがビンゴでした。

      UTF-16 UTF-8 BOM 0xFEFF → 0xEFBBBF BOMの反転 0xFFFE → 0xEFBFBE
      str = str.gsub(/\xEF\xBB\xBF|\xEF\xBF\xBE/,"")

      元のStringにBOMが混入していた原因は不明。本当に文字コードはくだらないところでハマりますね。


        at 19:04 |
        2010/10/26

        JRuby と IronRuby と Ruby-mingw32 のスレッド実装の違い

        ruby 

        先日からRubyのスレッドの挙動に振り回されている*1わけですが、これまでに試したのはmingw32版のv1.8.7とv1.9.2だけでした。結論としては、これらの実装からマルチスレッドでWin32OLEオブジェクトの呼び出しを行うと、プロセス全体がブロックしてしまうようです。

        それではJavaで実装されているJRuby や、.NET Frameworkで実装されている IronRuby の実装はどうなっているのだろうという疑問が湧いたので、今日はこれらの実装で先日のプログラムを流して、これらがどのような挙動を示すのかについて調べてみました。結論から述べると、これらの実装はWin32OLEのようなネイティブのライブラリを呼び出しても、他のスレッドがブロックすることはありませんでした。本家版のRubyと、JRubyやIronRubyは厳密にはスレッドの挙動が異なっているようです。

        [JRuby と IronRuby と Ruby-mingw32 のスレッド実装の違い の続きを読む]

        at 17:32 |
        2010/10/18

        RubyのWin32OLEは現状でマルチスレッド対応ではないらしい

        ruby 

        先日書いたエントリのサンプルには問題があって、スレッドは切り替わるもののWin32OLEの呼び出し部分でブロックしてしまうので、Ruby 1.9にしても本質的にはうまく実行できません。前回は待ち時間が短かかったのと、タイムスタンプを出力していなかったのでスケジューリングがめちゃくちゃなことに気づいていませんでした。

        また、Ruby 1.9.2のWIN32OLEの欄にも以下の注意書きがあったのですが見落としていました。

        class WIN32OLE

        マルチスレッドでの利用制限
        注)以下の記述はWIN32OLEの将来のバージョンの仕様を規定するものではありません。
        WIN32OLEはシングルスレッドモードでCOMとインターフェイスします。このため、ruby 1.9以降のRubyのThreadとネイティブスレッドが1対1で対応する実行環境ではスレッドをまたがる呼び出しはエラーとなります。

        ということで、現在のところWin32OLE内でブロックするプログラムをマルチスレッドでうまく動かす方法はないようです。Win32OLEマルチスレッド対応という話もあるようなので、もしかしたらもう少しで解決されるのかも知れないので、期待して待ちたいと思います。

        [RubyのWin32OLEは現状でマルチスレッド対応ではないらしい の続きを読む]

          at 22:42 |

          Rubyのスレッドをたたき起こす

          ruby 

          Rubyでsleepを呼んで眠っているスレッドむりやり実行状態に戻す方法(JavaだとThread.interrupt()にあたるもの)がないかと思って調べていたら、灯台下暗しでリファレンスマニュアルにThread#runで実行を再開できるとちゃんと書いてありました。sleepは組み込み関数ですが、runはThreadクラスにあるのでちょっと分かりづらいですね。

          組み込み関数 - Rubyリファレンスマニュアル

          sleep([sec])
          sec 秒だけプログラムの実行を停止します。sec には浮動小数点数も指定できます。sec が省略された場合、他スレッドからの Thread#run などで明示的に起こさない限り永久にスリープします。戻り値は実際に停止していた秒数(整数)です。

          確かに下記のようなコードを書いてみたらsleepがキャンセルされてスレッドが再開されることが確認できました。
          これでsleepで眠っているThreadをjoinしようとしてプログラムが固まってしまうという状況を回避できそうです。

          [Rubyのスレッドをたたき起こす の続きを読む]

            at 14:21 |
            2010/10/16

            Ruby/MySQL で Mysql::ProtocolError が出たときに確認すべきこと

            ruby 

            Ruby/MySQL を使って書かれたコードを Ruby 1.9 で動かそうとしたら、これまで見たことがないMysql::ProtocolErrorというエラーが出るようになってしまって参りました。

            結論から述べると Ruby 1.9 では -K オプションをつけるのはやめましょうねという話。

            試しに全く同じコードを Ruby 1.8 の環境に持って行ったところ、ちゃんと動作するので、じゃあ再現コードがどれだけシンプルにできるかと思ってどんどんコードを削っていったら、下記のようなごく簡単なコードでも再現することが分かりました。

            test.rb

            require 'rubygems' require 'mysql' conn = Mysql::connect('localhost','testuser','testpass','testdb') res = conn.query("select now()") res.each do |row| p row end

            一瞬、Ruby/MySQL が Ruby 1.9 に対応していないのかと思いましたが、ウェブには 1.9 対応と書かれているし、同じようなエラーで悩んでいる人も見あたらないので、何か手がかりはないかとひたすら試行錯誤していたら、偶然コマンドラインオプションをつけ忘れたときにうまく動くことを発見。そういえば、Ruby 1.9 は -Kx オプションは非推奨になってたことを思い出しました。

            C:\tmp>ruby test.rb ["2010-10-16 23:10:09"] C:\tmp>ruby -Ku test.rb C:/Ruby192/lib/ruby/gems/1.9.1/gems/ruby-mysql-2.9.3/lib/mysql/protocol.rb:629:in `read_eof_packet': packet is not EOF (Mysql::ProtocolError) from C:/Ruby192/lib/ruby/gems/1.9.1/gems/ruby-mysql-2.9.3/lib/mysql/protocol.rb:317:in `retr_fields' from C:/Ruby192/lib/ruby/gems/1.9.1/gems/ruby-mysql-2.9.3/lib/mysql.rb:321:in `query' from test.rb:5:in `<main>' C:\tmp>ruby -Ks test.rb C:/Ruby192/lib/ruby/gems/1.9.1/gems/ruby-mysql-2.9.3/lib/mysql/protocol.rb:629:in `read_eof_packet': packet is not EOF (Mysql::ProtocolError) from C:/Ruby192/lib/ruby/gems/1.9.1/gems/ruby-mysql-2.9.3/lib/mysql/protocol.rb:317:in `retr_fields' from C:/Ruby192/lib/ruby/gems/1.9.1/gems/ruby-mysql-2.9.3/lib/mysql.rb:321:in `query' from test.rb:5:in `<main>'

            こんな感じで、 -K オプションを使わなければうまく動くようです。ちょっと詳しい理由は分からないのですが、 -K オプションはストリームの入出力にも影響を及ぼしてしまうということなのでしょうか。Ruby 1.9 でストリーム関係のエラーが出た場合には -K オプションを使っていないかどうかという事を確認するようにした方が良さそうです。

            [Ruby/MySQL で Mysql::ProtocolError が出たときに確認すべきこと の続きを読む]

              at 23:28 |

              Ruby 1.9.2 に win32-service を入れる

              ruby 

              RubyでWindowsのデーモンを実装したかったので、Ruby1.9.2 に gem で win32-service をインストールしようとしたら、一筋縄ではインストールできなかったので、インストール方法をメモしておきます。

              作業の前提条件としてはWindowsにRubyInstaller for Windowsを使ってRuby 1.9.2がインストールしてあり、DevKit-4.5.0が正しくインストールされているものとします。インストール先はデフォルトのままなので、"C:\Ruby192"です。

              まず、gemで単純にインストールを試みると下記のような感じのエラーが出ます。

              C:\>gem install win32-service Temporarily enhancing PATH to include DevKit... Building native extensions. This could take a while... ERROR: Error installing win32-service: ERROR: Failed to build gem native extension. C:/Ruby192/bin/ruby.exe extconf.rb checking for RegisterServiceCtrlHandlerEx()... yes creating Makefile make C:/Ruby192/bin/ruby -e "puts 'EXPORTS', 'Init_daemon'" > daemon-i386-mingw32.def gcc -I. -IC:/Ruby192/include/ruby-1.9.1/i386-mingw32 -I/C/Ruby192/include/ruby-1.9.1/ruby/backward -I/C/Ruby192/include/ruby-1.9.1 -Iwin32 -DHAVE_REGISTERSERVICECTRLHANDLEREX -O3 -g -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -o daemon.o -c win32/daemon.c win32/daemon.c: In function 'Ruby_Service_Ctrl': win32/daemon.c:141:7: error: '__try' undeclared (first use in this function) win32/daemon.c:141:7: note: each undeclared identifier is reported only once for each function it appears in win32/daemon.c:142:7: error: expected ';' before '{' token win32/daemon.c: In function 'Service_Ctrl': win32/daemon.c:199:4: error: '__try' undeclared (first use in this function) win32/daemon.c:200:4: error: expected ';' before '{' token win32/daemon.c: In function 'ThreadProc': win32/daemon.c:279:7: warning: initialization discards qualifiers from pointer target type make: *** [daemon.o] Error 1 Gem files will remain installed in C:/Ruby192/lib/ruby/gems/1.9.1/gems/win32-service-0.7.1 for inspection. Results logged to C:/Ruby192/lib/ruby/gems/1.9.1/gems/win32-service-0.7.1/ext/gem_make.out

              この症状の類似の事例をネットで検索してみると「RubyForge: Win32 Utils: トラッカー詳細: 27692 win32-service install error with 1.9.1」が見つかりました。これによると__tryと__finallyマクロをコメントアウトしてしまえばとりあえずOKのようなのでコードを書き換えてgemを再生成してインストールすることにしました。

              [Ruby 1.9.2 に win32-service を入れる の続きを読む]

                at 21:34 |
                2010/10/12

                Ruby 1.8 と 1.9 のスレッドの違いにハマる

                ruby  mom 

                先日ちょっと書いたRuby から MSMQを使う話の続き。
                このプログラムをちょっといじって、スレッドを使って複数のキューを待つようにしてみたら、うまく動かなくて色々試行錯誤したのでメモ。

                結論から述べると、スレッドでやりたい場合にはRuby 1.9系に移行するのがいいみたいです。
                どうしても1.8でやりたい場合には、forkなどを使ってマルチプロセス化しないといけなさそうな感です。

                この対処方法は誤りです。現状のWin32OLEはマルチスレッド動作しません

                [Ruby 1.8 と 1.9 のスレッドの違いにハマる の続きを読む]

                  at 22:35 |
                  2010/10/02

                  Ruby から MSMQ を使う

                  ruby  mom 

                  MSMQでRubyからメッセージ受送信できる方法を調べてみたのでメモ。

                  ちょっと調べてみたところ、RubyにはMSMQ向けのライブラリはないようなのでWIN32OLE経由で呼び出だすことにします。よって、ホストがWindowsでない場合、以下のサンプルスクリプトは動作しません。MSMQのCOMのインタフェイスについてはMSDNの「メッセージ キュー COM コンポーネント」で調べることができます。

                  プログラミング自体はそんなに難しくはありませんが、ハマりやすいポイントとしてはキューがトランザクションキューかそうでないかで、受送信方法が異なることでしょうか。トランザクションキューにするか否かの設定はキュー作成時に行う必要があり、作成後は変更することができないので、うっかりキューの種類にそぐわない方法で受送信を行おうとするとうまくいきません。

                  [Ruby から MSMQ を使う の続きを読む]

                    at 22:40 |
                    «Prev || ... 2 · 3 · 4 · 5 · 6 · 7 · 8 · 9 · 10 ·... | | Next»
                    » ArchiveList (Tag for "ruby" )