How to test rack middleware

ざざっとメモ。

Middlewareの種類

一口に Rack middleware と言っても目的とする動作にはいくつかバリエーションがある。

  1. request を処理する middleware
  2. response を処理する middleware
  3. その他を処理する middleware ( middleとは? )

例えば Rack::Access や Rack::Cors, OmniAuth はアプリに到達する前の request を処理する middleware であり、Rack::ETag や Rack::Deflator は response を処理するものである。ExceptionNotification などはその他を処理する middleware である。

基本的にアプリは適当でよい

例えばこんな感じだ。

  • 適当な lambda を作って名前を付ける(#callを呼べればなんでもよい)
  • rspec や minitest/spec では let でもよい

この時に大事なのは、例外を起こす lambda にするか、あるいは期待する値を返す lambda にするかなど、「気にしていることだけを実現する lambda」を雑に作ってしまってよいということだ。Rails アプリであろうがなかろうが Rack middleware のレベルでは status code と headers と body の三つが揃っているというただそれだけのものになる。

テストしたいアプリをbuildする

テストしたい middleware を use してテストしたい条件の lambda を run するアプリを build する。

Rack::Builder.new do
  use Middleware
  run Application
end

これを call すれば Rack middleware のテストは行える。

テストで気にするものについて十分なパターンを用意する

  • request を処理するなら env のパターンが豊富になる1
  • response を処理するならアプリの lambda をいくつも用意する
  • その他の場合も恐らくアプリの lambda の準備を厚くする形になるだろう

例えば ExceptionNotification のようなものをテストしたいのであれば

Rack::Builder.new do
  use Middleware
  run lambda { |env| raise StandardError }
end

みたいなものが必要になる。

参考

  1. request の path や何らかの header について該当するかしないかのパターンを用意することになるはずだ。 

最新のfrontend技術を使いまくれる静的サイトジェネレータMiddleman

CoffeeScript を軽く試してみようと思ってあれこれ調べているうちにたどり着いた Middleman というツールを紹介してみる。

Middleman: Hand-crafted frontend development

たぶん試したのは 2.0.3 だか 2.0.4 だかその辺。

特徴

  • Sinatra based ( つまり ruby 製 )
  • Sass 自動コンパイル
  • CoffeeScript 自動コンパイル ( Sprockets を使った依存性解決も )
  • Sinatra で使える view の機能
    • HTML テンプレートは erb, haml, slim, markdown が利用可能
  • YAML で「データ」を持ってこれを view に反映できる
  • livereload 対応

そして、静的サイトとして出力できる。

利用技術

  • CoffeeScript
  • Sass
  • EventMachine
  • Thin
  • Guard Livereload

など、お馴染みな人にはお馴染みなもののオンパレード。

あと Ruby はたぶん 1.9 の方が良い。1.8 でも動くかもしれないけど、自分はうまくいかなかった。(後日ちゃんと動いたので大丈夫かも。)

インストール

gem install middleman

残念ながら EventMachine や Thin の辺りが native extension なので Windows ではややこしい。(あ、Mac でも XCode 入ってないとまずいです。)これらの gem にはそれぞれ Windows 版があるんだけど、なぜか Middleman がうまくそれらを利用できない。

gem 自体は全部入ってるのでうまくやれば使えそうな気はするんだけど、勇者募集中らしい。

Twitter / @middlemanapp: If you're a Rubyist on Win …

使い方

初期化から実行

middleman init PROJECT_NAME
cd PROJECT_NAME
middleman

とすると middleman server が立ち上がるので、

http://localhost:4567/

にアクセスして簡単な紹介文が表示されれば ok.

デフォルトではこんな感じでファイルができる。

PROJECT_NAME/
├── config.rb
└── source/
    ├── images/
    ├── index.html.erb
    ├── javascripts/
    ├── layout.erb
    └── stylesheets/
        └── site.css.scss

静的サイト生成

project のディレクトリで

middleman build

とすることで

build/

というディレクトリができてその中に生成済み HTML, JavaScript, CSS, そこから利用するファイルが配置される。

build 以下を Web サーバ配下に置けば静的サイトの公開終わり。

画像とかどこに置けばいいの?

middleman server が動いている状態なら

source/

の中の構造がそのままブラウザで確認できる。例えば index.html.erb の内容が http://localhost:4567/ に表示される。変換しないファイルも同様。

エンジンは拡張子で

init したばかりの状態で .erb と .scss があるのでなんとなく分かると思うけど、何を使うかは拡張子で指定する。例えば

source/javascripts/application.js.coffee

を置けば

http://localhost:4567/application.js

でコンパイル済みの JavaScript ファイルにアクセスできる。CoffeeScript を使わない場合は .js の拡張子でそのまま JavaScript を書けばよい。

index.html.erb じゃなくて index.html.slim を置けば slim を利用できる。

レイアウトの変更

config.rb を見ればまず分かると思う。その中から二つだけ取り出して紹介しよう。

template と layout を別々のエンジンで

set :markdown, :layout_engine => :slim

こうすれば

...
└── source/
    ├── images/
    ├── index.html.markdown
    ├── javascripts/
    ├── layout.slim
...

のように個々の文書は markdown で、layout を slim で書くことができる。

特定のディレクトリ以下の layout を全部変更

with_layout :layout_mobile do
  page "/m/*"
end

こうしておくと上の設定と合わせて

...
└── source/
    ├── images/
    ├── index.html.markdown
    ├── javascripts/
    ├── layout.slim
    ├── layout_mobile.slim
    ├── m/
    │  └─ index.html.markdown
...

こんな形で layout ファイルを分離できて、

http://localhost:4567/m/

以下はモバイル専用といった形で利用できる。スマートフォンであれば JavaScript が利用できるので、redirect を諦めれば静的サイトでも両対応サイトは十分実現可能だし、Middleman を使えばそのために2倍の HTML のコーディング量を要することもない。

YAMLデータを使ってコンテンツの使い回し

ここから先はまだ実際には試してないのでコード例は出せないけど、上の layout の切り替えに加えて

  • YAML に複数行データでコンテンツを持たせる
    • markdown などのルールから変換して HTML として展開

することで HTML のコーディングだけでなくコンテンツも再利用できると思う。

いずれ試してみたい。

その他

  • livereload でブラウザに切り替えて reload することなくファイルの変更を反映可能
    • ただし WebSocket を利用するのでブラウザを選ぶ
  • JavaScript や CSS の minify
  • Y! Smush.it を使った画像の最適化

などもできるらしい。ほんとになんでもアリだなぁ。

参考

livereload は昔からよくあるブラウザを自動でリロードするやつのモダンな実装。WebSocket を使うので 2011-08-10 時点では Firefox, Chrome ともに拡張を入れる必要がある。

最近は Mac のネイティブアプリ化に向けて頑張ってるらしい。完成したら「terminal で gem 入れて」とか何ゆってんの?な人でも使えるようになって面白いかも。

OSX で Google Calendar と同期できる何か

要求

OSX 10.4 で Google Calendar をブラウザを使わずに利用したい

正確には iCal のカレンダーを共有したい、だったんだけど、関係する人みんなの見れるサーバが必要だけど、それだったら Google Calendar 使った方がいいんじゃないの?ということでそっちの流れに。

選択肢

OSX 10.5 以降は標準で iCal が Google Calendar と同期できるらしいんだけど、10.4 では標準ではできないらしい。10.4 で現実的なのは

  1. Thunderbird + Lightning + Provider for Google Calendar
  2. iCal + GCalDaemon

くらいっぽい。

自分が使っているのが Lightning だったので 1 の方法をオススメした。

Thunderbird + Lightning + Provider for Google Calendar

Provider for Google Calendar を入れると「新規カレンダー」を作成する際に「ネットワーク上のサーバに保存する」の中に「Google カレンダー」という選択肢ができるので、そこに ICAL フォーマットのカレンダーアドレスを追加すれば ok.

public な calendar でも認証を要求されるみたい。まぁそのくらい我慢しろということで。

iCal + GCalDaemon

Tape » iCalとGoogleカレンダーの同期(OSX10.4の場合)

から辿った方法で実現できるらしいんだけど、今回は試してない。

shell スクリプトと Ruby スクリプトで設定を共有する

あらためて書くほどたいした話じゃないです。

細々した仕事をするスクリプトの多くは基本的に sh スクリプトが多いと思うのですが、やはり sh スクリプトでは多少荷が重い仕事もあります。awk や sed などを使うのはまぁ常套手段ではありますが、あんまり激しくコマンドを呼び出すとそれだけ負荷が高くなっていきます。そういう場合、自分は Ruby で書き直してしまうのですが、すでに稼働中の sh スクリプトを含めて毎回同じような設定を書いていることに気がつきました。わずか数行の代入文とは言え、なんかこれ無駄な感じがします。

sh スクリプトの変数代入は基本的に以下のように書きます。

VAR=VAL

自分の場合、sh スクリプトの変数は常に大文字で書くようにしているのですが、よく見たらコレ、

Ruby の定数定義と同じじゃん

と気づきました。しかも Ruby はバッククォートを使った別プロセスの結果の取得も sh スクリプトと同じように動きます。つまり、特別なフォーマット(XML やら YAML やら)を用意しなくても、特別なパーサを用意しなくても、同じ設定をそのまま sh でも Ruby でも読み込むことができるということです。

具体的にやることは以下のように、

sh と Ruby で設定を共有するイメージ

  1. 変数定義の部分を別ファイルに切り出し
  2. sh スクリプトでは . で 1 のファイルを読み込む
  3. Ruby スクリプトでは load で 1 のファイルを読み込む

だけです。

Ruby の方で定数はちょっと扱いにくいなぁと思ったら Object.const_defined?(), Object.const_get() を使って変数に取り込むことも可能です。

最初から小文字で変数を書いて Ruby でもローカル変数として取り込めばいいじゃんという意見もあるかもしれませんけど、Ruby スクリプト側は恐らくコードと設定の分離を意識して書きたいだろうから、ローカル変数にいきなり取り込むよりいったん定数で取り込んでおいて、それを必要に応じて使えるようにしておいた方が気持ちいいような気がします。で、この処理を module に追い出してしまえば毎回書く必要もありません。うん、いいアイディアだ。

psh - interactive shell with the power of perl

※ psh はログインシェルまでこなせちゃう shell です。Perl をインタラクティブに使いたいという、当初の目的からは外れそうです。

川o・-・)<2nd life - perl でインタラクティブなシェルを実現する perlsh

とか見て入れてみっかーと思って Debian etch(4.0) で似たような感じの名前を探してみたところ、

$ apt-cache search readline | grep perl
libenv-ps1-perl - prompt string formatter
libterm-readline-gnu-perl - Perl extension for the GNU Readline/History Library
libterm-readline-perl-perl - Perl implementation of Readline
librarieslibterm-readline-zoid-perl - Pure Perl implementation of Readline libraries

てな感じ。でもやはり perlsh コマンドとやらはインストールされない。cpan から入れているわけじゃないし、ソース展開して deploy なんていやなのねんと思い、気分を変えて FreeBSD の方で

$ make search key=perlsh | grep ^Path
Path:   /usr/ports/shells/perlsh

キター。ここで Makefile を読むと

MAN1=   psh.1 \
        pshcomplete.1 \
        pshconfig.1 \
        pshdevel.1

おや? psh ?

改めて

$ apt-cache search psh | grep perl
libpdf-api2-perl - provides the functions for creating PDF documents in Perl
psh - interactive shell with the power of perl

おっ。

apt-get install psh
$ psh
psh% File::Glob::<TAB>
AUTOLOAD                                bootstrap
GLOB_ALPHASORT                          bsd_glob
GLOB_BRACE                              constant
GLOB_CSH                                csh_glob
GLOB_ERROR                              doglob
GLOB_NOMAGIC                            glob
GLOB_QUOTE                              import
GLOB_TILDE

おぉ。豪快に補完される。

ステキ。

※ OSX 10.3 + PPC の環境では cpan からインストールしたあとに .cpan/build/psh-1.8 内で make install した。これで合ってるのかどうかよく分からないけど動いてる。Term::Readline::Gnu はコンパイルにコケるので、Term::Readline::Perl にした。

あーれー? なんか普通のコマンドも補完するな。んー? なんか思っていたのと違う?

OSX でウィンドウ切り替え

OSX では command + tab でアプリケーションの切り替えはできるんだけど、一つのアプリで複数のウィンドウを開いていた場合にそれらのウィンドウの切り替えをキーボードから行うことはできない。

と、思い込んでいたができた。

趣味の日記 OSXでのウィンドウ切り替え

10.3 の環境ではここで書いてあるのと違って

command + `

だった。ただし、Realforce + WinK ドライバ + uControl の環境では Shift + @ で入れる ` ではダメで、たまたま [半角/全角] に割り当てられていた ` を使ったら動いた。つまり、

command + `
command + tab

はキーボードで縦に並んでる状態になって、予期せずなかなか使い勝手のよい状態に。へー。

番組繰り上げってのもあるんだ

23:10 熱闘甲子園 (休止時、以降繰り上げ)

なんて記述を見かけた。げー。繰り上げの可能性あるんだ。なんか埋めろよ。

野球ってのは本当に迷惑なスポーツだなぁ。

すごい夏休み

i d e a * i d e a - 無敵会議の作り方

紹介されている本を夏休みの宿題にしようかなと思った〆切り前。

アフィリエイト狩り

「アドセンス狩り」にロックオン!

うーん、そんなものがあるとは。(まだちゃんと読んでないけど。)ちょっと遊びでこのサイトにも Apple Store アフィリエイト入れてみようかななんてことを考えていたのだけど、これは目に付くチャンスなのか?(違

WinSCP 3.6.7

putty core の security fix に対応。これ書いている時点では日本語版はまだ 3.6.6 だけど。3.6.6 でも対応しているみたいなんだけど、せっかくだから 3.6.7 まで待つか。

ここでも Wiki を立ててみた。

サイト全体のテイストを合わせるためにまず選んだのが Hiki. サイドバー対応に will をカスタマイズして、おーなかなかいい感じじゃーんと思っていたが、Hiki が必要としている strscan は shared library じゃないか。Ruby 1.6.8 な aaa cafe で動かそうってのはちょっと無謀だろうと思ってやめる。

VikiWiki を試してみる。相変わらず setup の意味が分かりにくいのと、認証を none にしても必ず認証が必要な予約ページが存在している。この不整合さはどうだ。コンセプトは悪くないと思うのに、どうしても使い始めるに至らない困った Wiki だ。

最終的には FreeStyle Wiki Lite に落ち着いた。FreeStyle Wiki が tDiary テーマコンパチなのは知っていたが、肥大している感じがどうしたものかと思っていたんだけど、FreeStyle Wiki のサイトに行ってから Lite の存在を思い出した。あーこんなもんでいいじゃないか。別に気張ったドキュメント書きに使うわけじゃないんだし。

ということで ぶくまく を用意してみました。ありがち具合がいい感じです。

cygwin フル mirror でびっくり

mail-archives/ を除いて全部 wget したところ、1.8GB に! まぁでも Linux ディストリビューション丸ごと落としたと思えば CD 3枚なのでこんなもんなのか。もう少しインストール/アップデートが速く手軽にできるんなら丸ごと落とさなくていいのになぁ。

About

例によって個人のなんちゃらです