2010-09-13
ruby の win32ole のメソッド名が UpperCamelCase で気持ち悪いので、underscore で使えるようにした
お仕事でエクセルのデータを変換する必要があって、でも VBA は勘弁して欲しいと思ってなんとかできないかなと思ってたら、ruby で COM を操作するライブラリがあるじゃないですか!
ところが、この ruby の win32ole はメソッド名が COM のまま。COM のメソッド命名規則的には UpperCamelCase らしいけど、ruby でそれは気持ち悪い。というわけで、ruby の win32ole のメソッドを underscore で使えるようにした
require 'win32ole' require 'active_support/inflector' class WIN32OLE alias_method :old_method_missing, :method_missing def method_missing(name, *args, &block) begin old_method_missing(name.to_s.camelize(:upper), *args, &block) rescue NameError old_method_missing(name, *args, &block) end end end # trial excel = WIN32OLE.new('Excel.Application') excel.visible = true workbook = excel.workbooks.add() worksheet = workbook.worksheets(1) worksheet.range('A1:D1').value = ['North','South','East','West'] puts worksheet.used_range.rows.extend(Enumerable).map {|row| row.columns.extend(Enumerable).map {|column| column.value }.join(",") }
どうでしょうか。ちなみに、active_support/inflector は camelize しか使ってないので、active_support を使わない場合は適当に置き換えてください。
2010-08-18
ruby で時間待ちテストを高速で終わらせる方法
お湯を入れると3分後に食べられる麺クラス
class Noodle def pour_water @time_of_poured = Time.now end def can_eat? (@time_of_poured + 3 * 60) > Time.now end end
テストケース(3分たったら食べられるか)
noodle = Noodle.new noodle.pour_water assert !noodle.can_eat? sleep(3*60) assert noodle.can_eat?
このテストは sleep を使っているので3分待たないと終わらない。
開発中になんどもカップ麺が出来上がるのを待ってる暇などない。
なので、適当に時間を進められるように Time クラスを改造した。
class Time @@default_now_method = self.method("now") @@n_seconds_early = 0 def self.now @@default_now_method.call + @@n_seconds_early end def self.set_early(seconds) @@n_seconds_early += seconds end end
これを使うと、上のテストはこう書ける。
noodle = Noodle.new noodle.pour_water assert !noodle.can_eat? Time.set_early(3*60) assert noodle.can_eat?
Time.set_early で直ちに時間を進めることができる。
仕事で「3秒待つ」みたいなテストケースが何個かあって結構頻繁にテストを実行するのでこう作った。
それから、sleep って不正確だしね。他のオーバーヘッドで遅くなっても Time.now は待ってくれない。
ほんとうのところは Time クラスをいじらず、Time のラッパを作ってあげたほうがよかったのかも。
resque on rails
installing
ruby script/plugin install git://github.com/defunkt/resque.git
rake redis:install PREFIX=..........
rake dtach:install PREFIX=..........
running
QUEUE=* rake resque:work # run worker
./vendor/plugins/resque/bin/resque-web # run resque web interface
defining queue class
class Hoge @queue = :hoge def self.perform(fuga) # perform this queue end end
enqueue
Resque.enqueue(Hoge, fuga)
2010-06-01

hudson が落ちる。
hudson 1.3.60
マスターを ubuntu で、スレーブを windows にしたときだけ発生。(マスタースレーブどっちも windows, どっちも linux のような他の組み合わせでは発生しなかった)
プラグインは無効にしてある。
checkout の途中で windows のスレーブが terminated になり、次のようなエラーがマスターで発生する。
Checking out a fresh workspace because C:\hudson\workspace\hello_hudson\Media doesn't exist Checking out http://192.168.(省略) FATAL: hudson.remoting.RequestAbortedException: java.net.SocketException: Connection reset hudson.remoting.RequestAbortedException: hudson.remoting.RequestAbortedException: java.net.SocketException: Connection reset at hudson.remoting.Request.call(Request.java:137) at hudson.remoting.Channel.call(Channel.java:551) at hudson.FilePath.act(FilePath.java:742) at hudson.FilePath.act(FilePath.java:735) at hudson.scm.SubversionSCM.checkout(SubversionSCM.java:653) at hudson.scm.SubversionSCM.checkout(SubversionSCM.java:601) at hudson.model.AbstractProject.checkout(AbstractProject.java:1044) at hudson.model.AbstractBuild$AbstractRunner.checkout(AbstractBuild.java:479) at hudson.model.AbstractBuild$AbstractRunner.run(AbstractBuild.java:411) at hudson.model.Run.run(Run.java:1241) at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:46) at hudson.model.ResourceController.execute(ResourceController.java:88) at hudson.model.Executor.run(Executor.java:124) Caused by: hudson.remoting.RequestAbortedException: java.net.SocketException: Connection reset at hudson.remoting.Request.abort(Request.java:257) at hudson.remoting.Channel.terminate(Channel.java:598) at hudson.remoting.Channel$ReaderThread.run(Channel.java:880) Caused by: java.net.SocketException: Connection reset at java.net.SocketInputStream.read(SocketInputStream.java:185) at java.io.BufferedInputStream.fill(BufferedInputStream.java:235) at java.io.BufferedInputStream.read(BufferedInputStream.java:254) at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStream.java:2265) at java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInputStream.java:2558) at java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2568) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1314) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:368) at hudson.remoting.Channel$ReaderThread.run(Channel.java:856)
2010-04-03
Windows 用コマンドランチャー TeaLauncher 開発経緯
愛用していたコマンドランチャ "bluewind" の開発者のサイトが消えてしばらくたちました。再配布サイトは存在しますが、開発が続行することは期待できません。
bluewind にはいくつか問題がありました。コマンド入力時にクラッシュしたり、IME 関連で不具合がありました。
それでも愛用し続けていたのは、その補完機能が魅力的だったからです。
それは非常にシンプルで、設定しだいでは zsh の "unsetopt auto_menu" をしたときの挙動をまねることができたからです。候補が複数あるときに共通部分まで補完して候補リストを出すものです。
多くのコマンドランチャーはその機能がなく、bash のデフォルト設定のような候補が複数あっても見つかった順に全部補完してしまう挙動のものばかりです。
この動作は僕にはあいません。すばやく間違いなく入力するのに絶対必要な機能だと思うのですが。
ただ、bluewind の IME 関連の不具合いは耐えられなくなりました。入力モードにすると IME 入力モードを英数にする機能を使っていたんですが、おそらく IME に対して間違ったフラグを設定してしまい、こちらも愛用している mayu の機能で日本語入力モードに切り替えることができなくなるという問題でした。
どうせもう開発が進むこともないし、色々問題を抱えていたこともあったので、自分で作ってしまおうと考えるまでに至りました。
TeaLuncher
そこで開発を開始したのが TeaLuncher
簡単な紹介をします。使い方についてはまた今度。
C# で .NET Framework で開発していますが、一部 IME 関係で Windows の API を利用しているので Windows 専用です。
bluewind に比べると設定項目はありませんし、グラフィカルなコマンド登録画面もありません。アイコンや起動オプションなど細かい設定も使えません。
使えるのは、コマンドに結わえ付けた URL, ファイルパス(引数付き), 一部の TeaLuncher の特殊な機能だけです。コマンドで引数を渡すことは可能です。
このように、自分に必要な最低限の機能をつけました。
github でオープンソースで開発しているので、関心がある方は機能追加などご自由にどうぞ。

