日々是鍛練 このページをアンテナに追加 RSSフィード

February 02(Thu), 2012

[] Jenkinsでバッチ管理するのが便利そう

バッチを管理したくて、けど、そんなに高機能なものは必要なくて、バッチ間の依存関係を定義できればいい。

最初、GearmanRabbitMQ等のジョブキューサーバを用意してそれ経由で管理しようと思ったけど依存関係を定義して、決まった時間にキックしたのち成功/失敗に応じて処理したいだけなので、わざわざジョブキューサーバなんて必要ないと思った。Jenkinsだと簡単に定義できて、管理もしやすい。

January 30(Mon), 2012

[] listchars=trail:$してたら気持ち悪いのでbuffer保存時に行末スペースを削除するようにした

行末スペースはコードをぐんにょりさせる原因の一つなので注意を促す意味で表示させるようにしたけど、

list
listchars=trail:$

コード書いてたり文章書いていても常に表示されるようになって、すごい気持ち悪くなったので、buffer保存時に行末スペースを削除するようにしました。

command! -bang -bar -complete=file -nargs=0 DeleteSpaceEachLine
\ execute ':%s/\s\+$//'

function! s:AutoUpdate()
  if expand('%') =~ s:savebuf_regex && !&readonly && &buftype == ''
    silent! DeleteSpaceEachLine
    silent update
  endif
endfunction

autocmd MyAutoCmd CursorHold * call s:AutoUpdate()
set updatetime=500
if !exists('s:savebuf')
  let s:savebuf_regex = '.\+'
endif

こっちの方が削除し忘れがないし便利。

January 11(Wed), 2012

[][] RSpecで終了ステータスをテストする

RSpecでアプリケーションの終了ステータスをテストしたい時があります。Rubyアプリケーションで、exit(Kernel::exit, Process::exit)が呼ばれるとSystemExit例外が発生します。riからexitの挙動のコードを抜粋すると、

begin
  exit
  puts "never get here"
rescue SystemExit
  puts "rescued a SystemExit exeption"
end
puts "after begin block"

ということで、例外を補足すれば書けるのでexpect {...}.to raise_error()で実現できますが、ここは一歩進んでCustom Matcherを作成してみましょう。

RSpec::Matchers.define :exit_with_code do |code|
  actual = nil
  match do |block|
    begin
      block.call
    rescue SystemExit => e
      actual = e.status
    end
    actual && actual == code
  end

  failure_message_for_should do |block|
    "expected block to call exit(#{code}) but exit"  + (actual.nil? ? " not called" : "(#{actual}) was called" )
  end

  failure_message_for_should_not do |block|
    "expected block not to call exit(#{code})"
  end

  description do
    "expect block to call exit(#{code})"
  end
end

spec_helper.rb等に定義しておくことで、

describe LocalPort do
  context "executed in no args" do
    it "should show usage and exit status is 1" do
      expect { LocalPort.parse_args([]) }.to exit_with_code(1)
    end
  end
end

と使えます。

January 09(Mon), 2012

[][] About Face第3版読んでます

About Face 3 インタラクションデザインの極意

漠然とですが以前から作ったものに対してユーザの反応を気にするようになってきて、そういったことを勉強できる本はないものかと思っていました。この本は、インタラクションデザインを提唱して、事例を交えつつ考察してて面白いです。一度流し読みで全体に目を通したので再度読み始めてます。

少し前に読んだデザイニング・ウェブインタフェースよりも、なぜ、そうするのかが考察されていて読んでいてにやにやしっぱなしです。

January 07(Sat), 2012

[] 最近の我が家の蔵書事情

最近、自分が所蔵する本をすぐに読めない状況に少しフラストレーションがたまってきている。ここひと月の間では、洋書はすべて、和書も何冊か電子書籍で購入していて、電車に乗っている間はiPhoneで読んだり、コード書いてる時にはマシンでも素早く検索したり、眺めたりしてまぁ便利なこと便利なこと。iPad3も何やら2月に販売されるとかされないとか噂されていて、たぶん買うんでしょう。

さてそうなると、昔、iPodを購入したときにリッピング祭りをしたように蔵書を電子化しようと。部屋にある技術書は合わせて200冊くらいで、ラノベやら文庫やら人文社会学系の本を合わせるとまぁそれなりの数になるわけです。東京に引っ越す前にScanSnapを購入して快適自炊生活を夢見たのだけど、それはやはり夢でしかなくて、自炊作業ほど時間の無駄(1分毎に割り込み処理が入り、本一冊を自炊する気は到底起きない)はないということが判明してからScanSnapはただのオブジェに成り下がってしまい、これどうしましょうという状況で。

ひょんなことから、水銀先輩からBOOKSCANのプレミアム会員サービスがよいという話を聞き使ってみようかなぁと思ったけど、すべての書籍を電子化するには、50冊/月なので単純計算して半年弱くらいはかかるわけです。しかも技術書の中には2冊分に相当する(メイヤー先生の著書とか)ものもちらほらあったり、その半年に払うプレミアム金額でいろいろ購入できたり、ほんとなんだよこれという状況で、時間があるときに自分で自炊するしかないのかなとか思ったり思わなかったりしている今日この頃。

[][] lambda の代わりに expect を使う

RSpecでたとえば例外のテストコードを書くとして、

it "should raise CommandError in unknown command" do
  lambda { LocalPort.command.find("foo") }.should raise_error(
    LocalPort::CommandError, "foo"
  )
end

このlambda {...}.shouldは読み手からしたら意図が伝わりにくいので、expect {...}.toを使うとすんなり読める。

it "should raise CommandError in unknown command" do
  expect { LocalPort.command.find("foo") }.to raise_error(
    LocalPort::CommandError, "foo"
  )
end

RSpec bookのSection13#Ch, ch, ch, ch, changesでexpectを使うサンプルコードが載っている。あとは、Relishにも詳しく書いてある。

[] WindowsからVirtualbox上のUbuntuで動作するプロセスにポートフォワードする

MacBook(今は亡き黒ポリカーボネート)を24inchモニタにつなぐと世界が止まるので、泣く泣く自宅のマシンで最強のスペックを誇るThinkpad X201sで作業しています。

なんとかしてLinux環境を手に入れたくてVirtualBox(Ubuntu)+putty+ssh(ポートフォワード)という荒業に落ち着いています。基本的に作業はターミナルで完結するものばかりですし。

ポートフォワードの設定(GUIマネージャ経由)

追記: VirtualBoxのGUIマネージャからポートフォワードを設定できることを知りました。

GUIマネージャ上で、ゲストOSを選択して設定->ネットワーク->ポートフォワーディングという流れで設定画面にたどり着けます。そこで名前、プロトコル、ホストポート、ゲストポートを設定するとポートフォワードされます。こっちのほうがどう考えても便利ですね。

ポートフォワードの設定

WindowsのVirtualBox上でubuntuサーバを動かしsshで接続するを参考に。VirtualBoxをインストールしたディレクトリにVBoxManage.exeがあるのでこれを実行して引数にゲスト名やプロトコルなどを渡す。

$ VBoxManage.exe setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/Protocol" TCP
$ VBoxManage.exe setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/GuestPort" 22
$ VBoxManage.exe setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/HostPort" 10022

RailsアプリをCygwinで作るのはさすがに限界を感じてきたのでHTTPもポートフォワードさせて、クライアントはWindowsにしてしまおうという魂胆です。HTTPもポートフォワード可能で、

$ VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/Protocol" TCP
$ VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/GuestPort" 3000
$ VBoxManage setextradata "ubuntu" "VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/HostPort" 13000

ゲストOSの画面を立ち上げない

sshでログインして作業するのであれば、ゲストOSの画面を立ち上げる必要はない。VBoxHeadless.exeを実行すればよいがコンソール(NyaOS使っています)が必ず一つ占有されてしまう。

$ VBoxHeadless.exe -startvm "ubuntu"

これでうまくいくと思いきや、

Error: failed to start machine. Error message: Configuration error: Failed to get the "MAC"

というエラーが発生する。つらつらと調べているとまったく同じようなことをしている人を発見。Vista Host Configuration error: Failed to get the ”MAC”

ここでゲストOSの設定ファイルやログファイルを確かめてみてよって教えてくれてるので見直すと、最初に設定したsshが

<Forwarding name="guestssh" proto="1" hostport="10022" guestport="22"/> 

という設定があったので

<Forwarding name="guesthttp" proto="1" hostport="13000" guestport="3000"/> 

という項目をすぐ下に追加して、ubuntu.xmlファイルの上の方に定義されている以下の、

<ExtraDataItem name="VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/GuestPort" value="3000"/>
<ExtraDataItem name="VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/HostPort" value="13000"/>
<ExtraDataItem name="VBoxInternal/Devices/pcnet/0/LUN#0/Config/guestssh/Protocol" value="TCP"/>

設定を削除したら起動するようになりました。わー。どうやらVBoxManage.exeを使うのが間違いだったようです。

ただ、ポートフォワードされるのでリクエストが遅い? と思いきやどうやらRailsアプリであればthin使うとかなり速くなります。これでサーバ側はUbuntu(Linux)だしクライアント側はWindowsと、ほぼ本番環境に近い構成で開発できるので、あれ、別にMacなくてもいいやってなってきています。