先生!.devじゃないドメインでPowを使いたいんです!!オフラインでも使いたいんです!!!

うぇっぶえんじにあーならばどこでもコード書きますよね?地下深くをすすむ会社帰りの地下鉄のなか、あるいは昼休みに公園の芝生でくつろぎながらなど。そんなとき、生命線であるインターネットから断絶されてしまうこともあります。すると、残酷にもPowすらも別れを告げてくるのです><

通常ならばPowによって.devドメインでアクセスできるRackアプリも、Pow本体もローカルで動いています。しかしながら、インターネットが断たれてしまうと、正確にはDNSサーバにアクセスできない状態になるとPowは使えなくなってしまいます。/etc/resolv.conf がなくなり、/etc/resolver/dev を参照しなくなってしまうのです*1。そうなってもRackupなりなんなりしてしまえば、ポートを指定してlocalhostにアクセスすれば開発を続けることはできます。できますが、PowのENVが使えなくなりますし、その時だけ別の方法でサーバを起動するのもなんとなく気がすすみませんね。ならば、なんとしても、どんな状況でもPowを使いましょう。ついでに .dev 以外のドメインでPowを使ってみましょう。

任意のドメインで使う

Powで .dev 以外のドメインを使うための設定がPOW_EXT_DOMAINSです。任意のドメインをPOW_EXT_DOMAINSに指定してやることによりPowへ向けることができるのです。ホームディレクトリの .powconfig へ記述します。なければ作りましょう。

% cat ~/.powconfig
export POW_EXT_DOMAINS=offline

f:id:marutanm:20110608220355p:image:right例として、offline としてみました。これだけではofflineドメインは有効になりませんので、Powを再起動、つまるところ再インストールしましょう。

# Powの再インストール
% powder install
# 設定されたか確認
% curl -H host:pow localhost/config.json

Pow使うならPowder入れておくだァーッ! - Meltdown Countdown で紹介したPowderをつかっています。
Powの設定をみるにはリクエストヘッダにhost:powをつけてlocalhost/config.jsonにアクセスをします。レスポンスには"extDomains":["offline"]が含まれていることでしょう。

DNSなんてまっぴらだ

これだけでは .offline ドメインがDNSでひけない→アクセスできないままです。そこで良い子の見方、hostsを編集します。

% sudo vim /etc/hosts
# 127.0.0.1 appname.offline を追記
% grep offline /etc/hosts
127.0.0.1 sinatra-pow-powder.offline

f:id:marutanm:20110608221424p:image:right
するとどうでしょう .offline ドメインでもPowを利用してRackアプリにアクセスできています。さらにこれはインターネットから隔絶されても有効なのです!!

まとめ

  • POW_EXT_DOMAINS を設定すると、Powで任意のドメインを使える*2
  • DNSがひけない状況でPowを使うには/etc/hostsを編集する
    • 手作業でやってるのがスマートではないですよね。なにか良い手がないものか・・・
その他、参考

MacOSX限定・Rails3での開発で使える超手間無しサーバ「Pow」 - Back yard : yuya_lush’s report
Powの動作の流れ、なるほどそうなっているのか、と。

*1:そのあたりの挙動はresolverのmanを参照くださいませ http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man5/resolver.5.html

*2:単に任意のドメインを使うならPOW_DOMAINSを使うという手もあるけど、DNSより優先される点に注意。くわしくは[http://pow.cx/manual.html#section_3.1:title=マニュアル]参照

Pow使うならPowder入れておくだァーッ!

Rackアプリ開発するならPowはもう常識だよね〜 - Meltdown Countdown で使いはじめた Pow は、今も順調かつ快適にうごいてくれています。ふと、プロジェクトのその後を追ってみるとなにげにバージョンが上がったりしています。何が変わったのかなーとマニュアルをみててみつけたPowderが便利だったのでご紹介。

Powder

rodreegez/powder · GitHub
Powを使ううえで必用な、アプリケーションへのシンボリックリンクを作成/削除や、restart.txtの更新、あるいはアプリケーションログのtailといった作業を一発で実行してくれるコマンドがこのPowderなのです。

インストール

gemを使います。

gem install powder
コマンド

~/.pow ディレクトリへのリンク作成・削除

% powder
# 引数なしでカレントディレクトリへのシンボリックリンク作成

% powder link bacon
# シンボリックリンクのファイル名を指定して作成

% powder remove
# シンボリックリンク削除

欲をいえば.rvmrcファイルも生成してほしいですね。まあ自分でカスタマイズしましょう。

その他サブコマンド

$ powder list
# ~/.pow以下のシンボリックリンクを一覧
# -l でも同じ

% powder applog
# アプリのログをtail -f

$ powder restart 
# powを再起動
# 要は、touch /tmp/restart.txt
# -r でも同じ

ログを見るのに「あれ、pow使うとどこにログでるんだっけ」といちいち調べることも、再起動するためにコマンド履歴からtouchをさがすこともなくなります。便利ですね。

この他にも、Powのバージョンアップなどできたりします。くわしくはREADMEを参照ください。

手元に適当なプロジェクトがないけどとりあえずPowderをためしてみたいなら、marutanm/sinatra-pow-powder · GitHub でもご利用くださいませ。

shouldaでcontextをネストしてみる

Rubyのテストフレームワークのひとつ Shoulda を使ってみました。

Railsならば素直にRspecなんでしょうが、せっかくPadrinoを使っているので。Padrino自体もテストにShouldaを採用しているようです。PadrinoといえばRake 0.9.0でテスト動かないよというIssueがrvmのせいだと決めつけてrvm開発者に反論され、うやむやにcloseされているんですがどうなんですかね。ちなみにRakeを0.8.7にバージョンを落としたら問題なくテスト動きました。

Shouldaではcontextという単位でテストを記述していきます。そしてcontextはネスト(入れ子に)できます。仕様を正確に記述するためには、ネストされた各contextがどういう順序で実行されていくのかを把握しく必要があります。そのため、次のようなサンプルを実行してみました。

outer contextの中にinner context 1と2 がネストされています。そして、それぞれのcontextにsetupとteardownがあります。実行順を把握するため各所でpをよんでいます。これを実行すると、次のような出力が得られます。

テスト自体はネストされたcontxtの1、2、そして外側のcontextの順で動作するようです。そして、各contextの前後でsetupおよびteardownがよばれています。外側のcontextに属したsetup、teardownはネストされたcontextの前後にも必ずよばれ、計3回よばれることとなります。これを把握しておけば、テストの一連の流れにおいて共通部分をどのようにまとめあげ、contextをネストすればよいかわかりますね。
さて、前述のサンプルテストコードでは、外側のネストされたcontextの後のshould文をコメントアウトしてしまっています。これをアンコメントした状態で実行すると次のような出力がえられます。

外側のcontextのshould文ついては、後のものだけが実行され、先ほどの "outer context 1 test" は実行されていないようです。これについては、contextをもう一段ネストしてやって回避するなどの対策が必要となりそう。あるいは、テストコードに列挙された仕様を、テストの流れに沿ってDRY UPしていく過程では今回のサンプルのようにネストされたcontextの前後にshould文が生じることはないのかもしれません。
正しく、そして美しいコードは、仕様を正確に反映したテストからうまれます。偉そうに言い切ってみましたが、恥ずかしながらテストを書いてみたのは今回が初めてです。ごめんなさい。でも、きっとそうです。仕様をテストコードに落とすという行為は考えを整理することにもつながりますし、開発には欠かせないステップだと、今は思います。テスト書こう。テスト書こう。大事なので2回いいました。

Omniauthを使ったPadrinoアプリのチュートリアル 〜Mongoidを添えて

Blog Padrino and OmniAuth Overview - Padrino Ruby Web Framework でOmniauthを知り、便利そうだな〜と思ってから早14日。ようやく動かしてみました。
ActiveRecordの代わりにMongodb、ORMにはMongoidを使っています。基本的には上記ブログ記事にしたがって作業をすればいいのですが、Mongoidを使ったことによる変更点がいくつか。

Mongoidつかうための変更

プロジェクト作成
% padrino gen project omniauth --orm mongoid --tiny

ORMにMongoidを指定してプロジェクトを作成します。

モデル


PadrinoのAuthenticationHelperで使われているfind_by_idを定義しておきます。

コントローラ


もちろんDBにアクセスするところも変わります。DBに既存かどうかチェックする、なかったら新規作成。もっとMongoidらしい書き方もあるとは思いますが、今回は RailsApps/rails3-mongoid-omniauth · GitHub を参考にしました。

環境変数ENVを使う

twitterのoathを使う場合にはConsumer secretとConsumer keyがそれぞれ必要となります。冒頭のPadrinoブログに従うとコード中に直書きしていますが、これは避けたいですよね。
今回つくったPadrinoアプリの動作確認にはPowを使ったのですが、Powでは .powenv というファイルを使うことによって、環境変数ENVを設定することができます。Padrinoアプリのコードからはこの環境変数をよみこむようにしてやれば、アプリのコードとoauthに必要な情報を分離してやることができますね。
ちなみに、この環境変数ENVを使う方法はHerokuでもそのまま使えるので便利ですよね!

まとめ

まとめ
ちょっと凝ったwebアプリを作る上ではユーザごとのアカウントに対応した処理というのは不可欠だと思います。ユーザの管理なんかは既存のwebサービスに任せて、簡単にユーザとアカウントの紐づけだけをできるOmniauthのようなプラットフォームはぜひとも便利に利用したいですよね。そして、そういったちょっと凝ったwebアプリをつくるならページ数も増えてくるでしょうし、SinatraよりもPadrinoのほうがよさそうですよね。え、そもそもRailsを使えばいいんじゃあ・・・?そうですよね、使おうRails

marutanm/padrino-mongoid-omniauth · GitHub

MacでMongoDBをDaemon化して自動起動させる

Mongoidをつかって色々とためしているわけですが、それを使うにはもちろんMongoDBが起動している必要があります。

% mongod -dbpath /usr/local/var/mongodb/ --logpath /usr/local/var/log/mongodb/mongodb.log &

今までは使う都度、上記のコマンドで起動していました。都度といってもだいたい起動しっぱなしなので、Macを再起動するたびにといった感じ。 ちなみに、HomebrewでインストールしたMongoDBなので、dbpathとlogpathをそれぞれ指定して、Homebrewが使うディレクトリ内で完結するようにしています。どうせ毎回起動するんだからと、そろそろ自動起動するようにしちゃってもいいかなと思い始めました。

以下、MongoDB Startup Item for Mac OS X Snow Leopard - Hunter Ford を参考にしつつ作業してみた過程など。

plistファイル

/Library/LaunchDaemons に org.mongo.mongod.plist を設置。

冒頭のコマンドにあわせて、パスを指定してあります。

この際、Vimで空ファイルから作成すると、launchctl: no plist was returned for: /Library/LaunchDaemons/org.mongo.mongod.plist などエラーがでて実行できないときがありました。かといってXcodeでplistファイルを編集すると com.apple.xcode.PlistType なんて拡張属性がついてVimからとても編集しづらいファイルができあがってしまいます。なので、既存のplistファイルをコピーしてmongod.plistに仕立て上げるのがよさそう。そうすればファイルオーナーを気にする必要もなくなるし。今回はPowのplistファイルをもとに作成しました。

起動
# launchctl load /Library/LaunchDaemons/org.mongo.mongod.plist

起動後、ps でmongodプロセスがいることを確認。
終了させる場合はunload

まとめ

daemon化したい場合、plistファイルを作成すればほぼ完了。簡単でいいですね。


MongoDB for Web Development (Developer's Library)MongoDB: The Definitive GuideThe Definitive Guide to Mongodb: The Nosql Database for Cloud and Desktop ComputingScaling MongoDB50 Tips and Tricks for MongoDB DevelopersNoSQLデータベースファーストガイド

Vundleで管理してるプラグインの特定のバージョンを使いたい

すべてはwombatからはじまった

Vimを起動すると Cannot find color scheme wombat256 との表示。そんなはずはない。wombat256は入っている。Vundleを使って入れたのだ、間違いない。 .vimrc にだってこう書いてある。

Bundle 'wombat256.vim'

~/.vim/bundle 以下にだってちゃんとwombat256.vimはある。「もしかしたらVundleはカラースキームには使えないのか?」という疑念が頭をよぎる。こうして、wombat256.vim を使えるようにするための旅がはじまった。

Vundle はちゃんと動いているのか

Vundle自体は問題なく動作していて、すこぶる快適に使えていた、はずだった。基本的には問題なく動作しているのだけど、まさかカラースキームが読み込まれていなかったなんて。そういえば慣れ親しんだVimとはちょっと表情が違っていた。
ちなみに、このエントリ で書いたように、Vundle自体もVundleで管理している。その後、Vundle本体のアップデートも :BundleInstall!で可能であることも確認できた。

~/.vim/bundle/wombat256.vim のなかみ

答えはそこにあった。colorsの中にあったのは wombat256mod だったのだ。mod?もっど?モッド?
.vimrcの記述は先の通り。すると、参照されるのは vim.org のはず。
そう、そこにある最新版は2.0modなのだ。wombat256modを読み込むようにすれば解決?
否、使いたいのはwombat256なのだ。

Vundleでバージョン指定インストール

gmarik/vundle · GitHub を参照しても、プラグインのバージョンを指定する方法は見当たらない。READMEのTODOに次のような記述があった

  • allow specify revision/version?

つまり、将来的にはバージョン指定ができるようになるかもしれないが、現状は単純にプラグインを常に最新の状態にしておくためのものなのだ。

では、どうする

困ったときは、現場だ。現場にいけ。

% cd ~/.vim/bundle/wombat256.vim/
% ls -a
.      ..     .git   README colors

.git がいる。
そう、Vundleでいれたプラグインは実はすべてgitで管理されている。git-logをみるとmodではないころの歴史もたしかにそこに刻まれていた。そうとわかればあとは簡単。
git-checkoutすれば解決。

あれ、でも?

なんでwombat256のgitリポジトリが存在しているのだろう?.vimrcのBundleで明示的にgithubのリポジトリを指定しているならばわかる。bundle以下にgit-cloneしているのだろうから。しかし、今回wombat256はそうではない。vim.orgが参照されるのではないのか?

その時、声が聞こえた。「ソース読め」と。
該当部分は ここ のようだ。

  else
    let name = arg
    let uri  = 'https://github.com/vim-scripts/'.name.'.git'

Vundleでは、非gitリポジトリをBundleしようとすると、githubのvim-scriptsにあるgitリポジトリを参照してcloneするのだ。
つまり、次の書き方は同一の意味となる。

Bundle 'wombat256.vim'
Bundle 'vim-scripts/wombat256.vim'

まとめ

  • VundleでVundleを管理していても、本体のアップデートは問題なく可能
  • Bundle対象でvim.orgにあるプラグイン名だけ指定すると、自動的にgithubのリポジトリが参照される
  • プラグインの特定のバージョンを使いたい場合、そのバージョンをgit-checkoutすればよい