Home

UKSTUDIO

rails3でprimary keyとforeign keyをbig intにする

以下は、PostgreSQLの例。

ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = 'bigserial primary key' 


外部キーの場合、t.references :userとか書いてると、ActiveRecord側でintegerがハードコーディングされているのでlimitオプションを付けるしかなさそう。

t.references :user, :limit => 8

LVMを使っているKVMのディスクイメージの容量を追加する

KVMのディスクイメージの容量を増やしたのでメモ。

イメージファイルの拡張

まずはイメージのフォーマットを確認する。qemu-imgのinfoでわかる。

$ qemu-img info vm.img

今回はqcow2になっていたのでrawに変換する。

$ qemu-img convert -f qcow2 vm.img -O raw vm.raw

ddのseekを使って末尾に領域を追加する。10GBのイメージに5GB追加するならこんな感じ。

$ dd if=/dev/zero ov=vm.raw bs=1G count=5 seek=10

フォーマットを元に戻す。

$ qemu-img convert -f raw vm.raw -O qcow2 vm.img

仮想マシンのパーティションの修正

その後、イメージを立ち上げてパーティションを修正する。今回のパーティションは/dev/hda1がboot、/dev/hda2がlvmになっていたので/dev/hda2の方を修正する。

$ fdisk /dev/hda
> d
> 2 # /dev/hda2を一旦削除
> n
> p
> 2
> Enter
> Enter # /dev/hda2を作りなおす。デフォルトでサイズが拡大するはず。
> t
> 2
> 8e # /dev/hda2のパーティションタイプをLVMにする
> w
> q # 書きこんで終了
$ reboot

ボリュームの追加

$ vgextend VolGroup00 /dev/sda2
$ lvextend -L +5GB /dev/VolGroup00/LogVol00
$ resize2fs /dev/VolGroup00/LogVol00

思い出しながら書いてるから細かいところで違うかもしれないけど、だいたいこんな感じで容量の追加が完了。

Gentooデビューしました

メインの開発マシンのOSをUbuntuからGentooにしました。Gentooにした理由は割となんとなくだけど、強いて言うならGentooいいよっていう人の気持ちを知りたいのと、あとPortageは割と好きだからかな。Ubuntuに不満があったわけでもない。Unityは好きじゃないけど、どうせXMonad使うし。

インストールは第2回 Gentoo Linux インストール講習会 : ATNDに参加したおかげで起動するまでは割とすんなり(Thanks @ursm, @kenchan)。Funtooもいれて、実際起動するところまでは持っていったけど無線LANの設定とかがGentooのドキュメント通りじゃなくて混乱したので今回はやめた。

Gentooのインストールは色々と勉強になった。パーティション切るのも中学生の時に本に従ってLinuxいれた時以来だし、GRUBに至っては触ったことなかったし。ほかにもカーネルやXとかの設定とか、普段は動くものがすぐそこにあるだけだから意外に知らないのよね。

とりあえず今はXfce4 + XMonadの環境を作った。XMonad単体の方がいいんだけど、PDFリーダとかメッセンジャーとか何使ったらいいかわからなかったからとりあえずXfce4を使うようにした。GNOME3いれようとしたけど挫折。

そんなわけでしばらくはGentoo生活を送ります。

IPv6 Hackathonに参加してきた

この間のLL PlanetsでIPv6 Hackathonとやらに参加してきた。Ruby組は僕と @sugamasao と @takano32 の3人でチーム組んだ。

RailsはIPv6でも大丈夫っぽい

大丈夫っぽいっていうのは軽くさわった程度なので断言できるほどでもないため。IPv6でRailsを立ち上げたかったら上記のように–bを指定すれば大丈夫です。

rails server --b="::"  -p 3000

Unicornの場合もオプションで大丈夫。

unicorn_rails -l '[::]:3000'

あとはApacheは対応してるし一応なんとかなるのではないか。Nginxとかthinは調べてないのでわからないです。あとMySQLはIPv6に対応していないらしいけど、データベースはWebサーバから見えれば大丈夫だし何とかなるでしょう。きっと。

github.comやrubygems.orgはAAAAレコードがない

digコマンド叩けばわかるけど、みんな大好きgithub.comとrubygems.orgにはAAAAレコードがありません。ということで、IPv6オンリーな環境だと使えないと思うのでトンネル掘るなりなんなりの対応が必要っぽい。

今回作ったもの

ネタアプリを作っただけなので実装としてはそんなにおもしろいものでもないかな。

ひとつは、twitterの発言ひとつに対してIPv6のアドレスをひとつ割り振って、そのIPv6にリクエストがきたらそれに対応するtwitterの発言を表示させるというもの。ただのアドレスの無駄遣いですね。

あと1時間ぐらい僕の時間があまったので、その1時間でIPv6アドレスをキーとするストレージっぽいものを作った。あるIPv6に対してPOSTするとbodyの内容が保存されて、GETすると保存された内容が取得できるみたいな。更新はPUTだろっていう話もあったけど、時間が足りなかったのでした。

発表資料がそのうち公開されると思います。
Lightweight Language Planets : 公開資料

Net::HTTPとURI

そのストレージのテストをするのにRubyでNet::HTTPとURIを使って画像をPOSTするコードを書いた。その時にちょっとハマったことがあるので説明しておく。

IPv6は:を使ってアドレスを区切るので、ポート部とわけるために[]を使うことがある。そのアドレスをURI.parseしたあとにURI::HTTP#hostで値を取得すると[]が残ったままになり、Net::HTTPは[]があるとどうやらダメっぽくてエラーがでる。パッと見コードに何も問題がなさそうに見えるので知っておかないとハマる人はハマりそう。実際に僕はハマりました。

で、たまたまURI::HTTP#hostnameというメソッドがみつけてこっちは[]を取り除く。このURI::HTTP#hostnameはるりまを見るとどこにも乗ってなくて、挙動の違いはバグかとも思ったりしたんだけどどうやら違うみたい。

Rubyのuri/generic.rbを見ると以下のように書いてあった。

# Since IPv6 addresses are wrapped by brackets in URIs,
# this method returns IPv6 addresses wrapped by brackets.
# This form is not appropriate to pass socket methods such as TCPSocket.open.
# If unwrapped host names are required, use “hostname” method.
#
# URI(“http://[::1]/bar/baz”).host #=> “[::1]”
# URI(“http://[::1]/bar/baz”).hostname #=> “::1″

ということで、hostnameメソッドを使いましょうという話でした。

TDDBC 東京 1.6でサポートスタッフをやってきました

TDD Boot Camp 東京 1.6にRubyのサポートスタッフとして参加してきた。

当初の予定ではあくまでサポートなのでペアプロには参加しない予定だったけど、Rubyのグループが5人で人数が奇数になってしまったので急遽ペアプロに参加することにした。

この辺は@t_wadaさんや主催の@pocketberserkerさんとも相談してペアとトリオのふたつに分けるっていう話もあったけれど、僕が「せっかくだからペアプロして帰ってもらいたい」と思ったので若干の迷いはあれどペアプロに参加することにしたのでした。Ruby組は@takahashimさんや@1syoさん、@kwappaさんたちが参加されていて彼らなら付きっ切りでサポートしなくても大丈夫そうというのも理由のひとつ。

コードレビューを見た感じだと一応はうまくいったんじゃないかなと思う。特に@1syoさんと@takahashimさんのペア(ダブル高橋!)は積極的に質問をしてくれたので、僕としても教えがいがあった(えらそう)。ただ、質問を受けると僕の方のペアプロが一時的に中断してしまうし、僕としても頭の切り替えが結構大変だったので出来ることならやはり参加者同士でペアが組めるといいんだろうなぁ。理想を言うと全部のペアをスタッフ+参加者にすることなんだろうけど、あまり現実的じゃなさそう。

今回、最初に僕とペアを組んだ方が(お名前を聞くのを忘れてしまった…)モダンなテストの書き方を知りたいと言うので、ある程度xUnit的なテストの書き方でペアプロを進めた後、がっつりRSpec的な書き方にリファクタリングするということをやってみた。他のペアもRSpecは初期のit "なんちゃらかんちゃら"の書き方をされていたので、コードレビュー時に共有できたのはよかったのかな。RSpecの書き方については言っちゃいけないということはないだろうから言っちゃうけどそのうちるびまの方に書く予定なのでお楽しみに。

Ruby組は全体的にTDDのサイクル自体はできていた感じで、内容としてはテストの書き方にフォーカスが移っていたように感じる。例えば、標準出力が絡むテストのやり方とか、システム時刻が絡むテストのやり方とかdescribe/contextの切り方とか。多分、TDDBCも回数が増えていくにつれ、こういう人達がどんどん増えてくると思うからTDDBCの次の道をしめせるといいんじゃないかと思った。参考図書はいくつかあるけど、例えばxUTPとかTDDBCからのジャンプアップがヘビーすぎるなぁという気もする。(もちろんいきなりあれを全部読めという話でもないんだけれど)

話は変わって当日のお題を再度ひとりで実装してみたので、コードを公開しておきます。

ukstudio/tddbc1.6 – GitHub

あまりじっくり書いたって感じでもないので仕様漏れとかありそうだけど、テストコードの書き方の参考にはなるかと思います。@bleisさんみたいに細かに解説しようと思ったけど気力がないのでした。

そういえば今回のスタッフも若手が多いな。@bleisさんと俺が86世代、@kyonn_mmさんと@pocketberserkerさんがひとつだかふたつだか年下だっけ? 同世代の人が頑張ってるのはとても刺激になります。

最後に、主催の@pocketberserkerさん、講演をしてくださった@t_wadaさんをはじめ、スタッフの方々どうもお疲れ様でした。参加者のみなさま、どうもありがとうございました。

特に@pocketberserkerさんは佐賀の人なのにもかかわらず東京でTDDBC主催とか、そのパワフルさを見習いたい感じです。本当にお疲れ様でした。

おまけ

BDDについて自分なりにまとめてみた

BDDという言葉も割と人によって指すものが違うようなので「俺の中でのBDDはこうだよ」って内容のエントリ。別に絶対的なものでもないと思うので参考までに。

結論から

とりあえず結論だけ知りたい人向けに。

  • BDDにはふたつの種類がある
  • 1. TDDの言い換えのBDD(開発寄り)
  • 2. ATDD(受け入れテスト)でのBDD(ユーザ寄り)

振る舞い

BDDは振る舞い駆動開発と言われたりするように、テストという言葉のかわりに振る舞いという言葉を使う。日本語的には仕様と言うほうがわかりやすいかもしれない。

多分、BDDのイメージが掴みにくいのはこの振る舞いという言葉にあると思う。と言うのも振る舞いと言うのは、人の立場よって変わるからだ。例えば、プログラマがあるクラスを実装している時に言う振る舞いはそのクラスのメソッドとかの仕様になる。逆にユーザレベルの人が言う振る舞いはアプリケーションの要件・動作を言うだろう。

つまり、BDDという言葉はTDDからATDDの両方にかかるので文脈によって指すものがかわってくる。この辺は@t_wadaさんの言う「誰のためのテストか」を考える方がわかりやすいだろう。

TDDの別名としてのBDD

TDDにかかるBDD、つまりプログラマの為のBDDについて説明する。そもそもBDDという言葉が生まれた背景にはTDDに対する誤解がある。いわゆる「TDDのテストはテストじゃないよ」ってやつ。その誤解を避けるために生まれたのがBDD。多分「誤解を避ける」というのもあまり適切な表現ではない。と言うのもこの表現だとTDDを実践していない人の誤解を避けるために生まれた印象をうける。

実際はテストという言葉を使うことでTDDを実践する(しようとする)プログラマ自身にもよくない影響がある。例えばTDDの場合先にテストコードを書くので当然テストを書くときにテスト対象が存在しない。これは不自然だ。テスト対象がないことで、TDDに慣れていない人は「何をテストすればいいの?」と思うことも少なくない。

BDDではテストという言葉の変わりに振る舞いという言葉を使うと先程書いた。振る舞いという言葉を使うことで、テストという言葉から受ける違和感はなくなる。テスト対象が存在しなうちにテストを書くのは不自然だけど、なにかを実装する前に振る舞い(仕様)を決めるのは自然だ。

また、振る舞いに着目することでより良い設計ができるようになる。少なくとも僕はそう感じている。TDDでも先にテストコードを書くのでインターフェースに注意を向けることができるが、BDDの語彙を使うことでより実装と振る舞いを分離して考えられるからだと思う。

とは言え結局のところやることはTDDと変わらない。はたから見たら、TDDをしているのかBDDをしているのか区別つかないだろう。なのでここでひとつめの結論BDDはTDDの言い換えになる。もちろん使う言葉が違いプログラマに与える影響が違う以上、厳密にはTDDとBDDは違うものなのかもしれない。けれど個人的にはそこまでTDDとBDDの違いに厳密性を求めてないし、求める必要もないと思うので、プログラマ視点で見たときはほぼ同じという結論。

ATDDとBDD

ATDDはAcceptance Test Driven Developmentの略でAcceptance Testというのは受け入れテストのこと。TDDのよりレイヤの高いものだと思えばいい。Growing Object-Oriented Software, Guided by Testの画像がわかりやすいので拝借。

ATDDのひとつのサイクルでひとつの受け入れテストが完了し、それを繰り返すことでアプリケーションを実装していく。受け入れテストはどちらかと言えば顧客のためのテスト。受け入れという名の通り、このテストがパスすればその機能は実装が完了したとわかり、顧客の立場からすると要件が正しく実装されていること、進捗が管理しやすいなどの利点がある。

これとBDDに何が関係するのかと言うと、上で書いたようにBDDの振る舞いはユーザレベルで見たときはアプリケーションの要件・動作を指す。顧客は大抵の場合、ユーザレベルなのでこの場合での振る舞いは受け入れ条件となり得る。つまり、ATDDをBDDでやることは可能と言える。ATDDをBDDでやるメリットは、BDDでは振る舞いの言葉を使うのでより顧客・ユーザに近い言葉で受け入れテストを記述できるようになる(例:cucumberの日本語での記述とか)。

これがふたつめの結論のATDDでのBDD

ちなみにATDD自体も結構あやふやなやつで、何をテストするのかは受け入れ基準による。もし受け入れ基準が「とあるクラスに正しくメソッドが実装されていること」だとしたらどうなるか。これはややこしいけれど、ATDDのサイクルとTDDのサイクルの距離が大分近くなると思う。場合によってはTDDで書いたテストコードがそのまま受け入れ基準となり得ることもある。それでもTDDとATDDは目的が違うのでその辺は意識した方がいい。

Outside-In

BDDは上で説明したように、コンテキストで「振る舞い」が指すものが変わる。とは言え、根源となる思想はあってそのひとつがOutside-In。Outside-Inと言うのは外側から見た振る舞いを軸に内部を作りこんでいくということ。人によって見る位置が違うので「外側」がどこか変わってくる。プログラマならメソッドやクラスの外だし、ユーザならアプリケーションの外側。なので、BDDがなにかを一言で答えるとしたら振る舞いに着目して、それを軸に内側を作りこんでいくことになるのかなぁ。

再び結論

長々と書いて逆に混乱してきた人もいるかもしれないのでさくっとまとめ。

  • 結局は’誰が’、’誰の為に’、’何を’テストしているのかが重要である
  • TDDはDeveloper Testing。つまり僕達のためのもの。
  • ATDDはCustomer Testing。つまり顧客のためのもの。
  • BDDは振る舞いに着目する。状況・目的によって「振る舞い」が指すものが変わる。それに合わせて語彙も変わる。

なんちゃらDDはいっぱいあって、しかもそれらが色々な軸で交わったりしてすごいややこしい。TDD/BDD/ATDDと誰かが言った時は、大抵の場合暗黙のコンテキストがあるのでそこに気をつけよう。わからなかったら聞こう。「それは誰の為のテストで何をテストしているんですか?」

個人的にはBDDという言葉を使わないのは誰の為のテストかわかりづらいから。なので大体の場合はTDDとATDDのふたつを使うことが多い。BDDが僕達にくれたものは大きいけれど、その知見はTDD/ATDDに十分反映されている(もしくはされつつある)ので、普通にTDD/ATDDと言えばいいじゃないかって意見。BDDって言葉を使うとややこしくなるので僕は使いません。

おまえの言うBDDは間違ってる!!という人は突っ込みいただけるとありがたいです。

See also

BDDの導入 – Dan North – Digital Romanticism
ストーリーについて – Dan North – Digital Romanticism
XP Customer Testing

mongodb + node.js を軽く試した

mongodbのインストール

$ sudo aptitude install mongodb
$ mkdir /path/to/data
$ mongod --dbpath /path/to/data

mongooseのインストール

$ npm install -g mongoose

node.jsでmongodb扱うのに他にもライブラリあるみたいだけど、とりあえずnpmでサクッと使えるmongooseを使ってみる。

サンプル

軽く試しただけなので、詳細は LearnBoost/mongoose – GitHub を参照。

実行するとmongodbの中身はこんな感じ。

> db.users.find()
{ "_id" : ObjectId("4dce0fb5bad67a145c000001"), "name" : "AKAMATSU Yuki", "age" : 24 }

印象としてはActiveRecordっぽいというかORMっぽいというか。mongodb自体をそんなに触ってないからこのアプローチが正しいのかどうかはわからないけど、馴染みやすくはある。

duostackでnode.jsアプリを動かすまで

node.jsのインストール

何はともあれnode.jsのインストール。aptではなくgithubからリポジトリをcloneしてmakeした。最近はapt以外のものは$HOME/localに入れるルールでやってるのでnode.jsも同様に。node.jsをsudoで入れると結構ハマるみたいな話を聞くので特に理由がなければaptとかで入れるか$HOME以下に入れるのがよさそう。

$ git clone git://github.com/joyent/node.git
$ cd node
$ ./configure --prefix=$HOME/local
$ make
$ make install
$ which node
/home/ukstuido/local/bin/node

npmのインストール

duostackを使うのにnpmが必要なのでnpmもインストール。curl使う方じゃなくてmakeしてインストールした。curl … | sh の形式があまり好きじゃない程度の理由。

$ git clone git://github.com/isaacs/npm.git
$ cd npm
$ make install
$ which npm
/home/ukstudio/local/bin/npm

npmがインストールされる場所は特に指定しなくても$HOME/localに入った。node.jsの位置でも見てるんだろうか。よくわからない。

duostackのインストール

あらかじめ、Duostackのアカウントは取っておくこと。結構すぐ登録確認メールが来る。

duostackのインストールは-gオプションを付けないとnode_modulesディレクトリがカレントディレクトリに出来る。最初-gオプションを知らなくて困惑した。

$ npm install -g duostack
$ which duostack
/home/ukstudio/local/bin/duostack

アプリの作成とデプロイ

ここまで来るとDuostack · Docs: Quick Start Guideに従うだけでOK。

適当なディレクトリを作ってそこにserver.jsを置く。

$ mkdir sample
$ cd sample
$ vim server.js

git initしてやる。

$ git init
$ git add .
$ git commit -m 'init'

duostackコマンドでアプリケーションを登録。ここで指定したアプリ名がそのままドメインになる。

$ duostack create ukstudio
$ git push duostack master

無事にpushできればURLが表示されているはずなのでブラウザで確認する。今回の例だとhttp://ukstudio.duostack.net/になる。

こんな感じでduostackでnode.jsアプリを動かすところまで試してみた。herokuとかもそうだけど、こうサクッとアプリが動かせる環境があるのはうれしい。

次はnode.js + CoffeeScriptとか、もうちょっとアプリらしいアプリを作ってみようかな。

追記: duostackでCoffeeScriptを動かす

CoffeeScriptからコンパイルしたJavaScriptを乗せるんじゃなくて、CoffeeScriptそのものを乗せる方法。server.jsは必要っぽいのでそこからrequireする形にした。CoffeeScriptはアプリの中にインストールしておく。 これで一応動くことは動く。

$ npm install coffee-script

Vimをソースからビルド

aptで入れたvimのrubyインターフェースのバージョンが1.8.6なのが気にいらなくてvimをソースからビルドした。

$ hg clone https://vim.googlecode.com/hg/ vim
$ hg update vim73

$ cd vim
$ ./configure --enable-multibyte --prefix=$HOME/local --enable-rubyinterp

これでOK。aptで入れたvimも一応残しておきたかったのでprefixで$HOME以下にビルドするようにした。Rubyインターフェースはrvmで入れた1.9.2を見るようになっていたのでとりあえずよしとする。何でrvmの奴を見にいったのかはよくわからない。

CoffeeScript + QUnitでTDD環境作ったよ

Rails3.1からCoffeeScriptがデフォルトで入ってるとかなんとかで、とりあえずCoffeeScriptだけで少し触ってみた。とりあえずQUnit自体もCoffeeScriptで書けるようなTDD環境を作ってみた。

とりあえず、UbuntuにCoffeeScriptをインストールするわけだけどaptの方が古いしせっかくだから最新のを触るかと思ったのでgithubからCoffeeScriptとnode.jsのリポジトリをcloneしてインストール。

$ git clone git://github.com/joyent/node.git
$ cd node
$ ./configure
$ make
$ sudo make install
$ node -v
v0.5.0-pre
$ git clone git://github.com/jashkenas/coffee-script.git
$ cd coffee-script
$ sudo bin/cake install
$ coffee -v
CoffeeScript version 1.1.0-pre

ディレクトリ構成はこんな感じ。coffeeにCoffeeScriptに入れて生成されたJavaScriptはsrcにいれるルール。test/index.htmlはQUnitの結果を見るため。test/qunitはずばりQUnitそのもの。

./coffee/hello.coffee
./src/hello.js
./test/index.html
./test/qunit/qunit.css
./test/qunit/qunit.js
./test/coffee/test-hello.coffee
./test/src/test-hello.js

CoffeeScriptは-wでファイルの変更を監視してコンパイルしなおすことができるので,以下の用に実行しておけばそれぞれ変更があったらコンパイルしてくれる。CoffeeScriptはデフォルトでfunction(){}();で囲って外部からアクセスできなくなるので,-bを付けてトップレベルにJavaScriptを生成するようにする。

$ coffee -w -b -o src/ -c coffee
$ coffee -w -b -o test/src -c test/coffee

これでテストコードもしくは本体のコードを修正すれば勝手にコンパイルするのでtest/index.htmlを見ればよい。後はもうちょい頑張ってブラウザを勝手にリロードするか,Rhinoとか使えばindex.htmlを用意しなくてもCUIでテスト結果をみれそう。

一式は以下のgistに置いた。(Qunitはライセンス見てないので外してある)
CoffeeScript+QUnit — Gist

Home

Feeds
Meta
Others

Return to page top