January 30(Mon), 2012
■[vim] 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][ruby] 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 07(Sat), 2012
■[life] 最近の我が家の蔵書事情
最近、自分が所蔵する本をすぐに読めない状況に少しフラストレーションがたまってきている。ここひと月の間では、洋書はすべて、和書も何冊か電子書籍で購入していて、電車に乗っている間はiPhoneで読んだり、コード書いてる時にはマシンでも素早く検索したり、眺めたりしてまぁ便利なこと便利なこと。iPad3も何やら2月に販売されるとかされないとか噂されていて、たぶん買うんでしょう。
さてそうなると、昔、iPodを購入したときにリッピング祭りをしたように蔵書を電子化しようと。部屋にある技術書は合わせて200冊くらいで、ラノベやら文庫やら人文社会学系の本を合わせるとまぁそれなりの数になるわけです。東京に引っ越す前にScanSnapを購入して快適自炊生活を夢見たのだけど、それはやはり夢でしかなくて、自炊作業ほど時間の無駄(1分毎に割り込み処理が入り、本一冊を自炊する気は到底起きない)はないということが判明してからScanSnapはただのオブジェに成り下がってしまい、これどうしましょうという状況で。
ひょんなことから、水銀先輩からBOOKSCANのプレミアム会員サービスがよいという話を聞き使ってみようかなぁと思ったけど、すべての書籍を電子化するには、50冊/月なので単純計算して半年弱くらいはかかるわけです。しかも技術書の中には2冊分に相当する(メイヤー先生の著書とか)ものもちらほらあったり、その半年に払うプレミアム金額でいろいろ購入できたり、ほんとなんだよこれという状況で、時間があるときに自分で自炊するしかないのかなとか思ったり思わなかったりしている今日この頃。
■[rspec][ruby] 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にも詳しく書いてある。
■[virtualbox] 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なくてもいいやってなってきています。


