| @技術/プログラミング
gem install chef # => 11.6.0 が入る
gem install knife-solo # => 0.2.0 が入る

入門 Chef Solo には knife-solo は 0.3.0 を使えとある。

gem install knife-solo --pre # => 0.3.0.pre5 が入る

knife solo ○× したときに solo なんていうサブコマンドないと怒られる。

knife-solo 0.3.0 使いたいなら chef のバージョンは 11.4.4 に落とさないといけない。ローカルマシンの Chef のバージョンだけでなく、リモートのやつのバージョンも落とさないといけない。この辺地獄っぽい。

プロビジョニングツール的なやつ、使えたら便利なんだろけど自分は環境作るのってもの凄くたまにしかないし Chef とか Puppet の使い方覚えるより手動でインストールしていった方が速いような気がする。Nginx をインストールするのにもの凄く時間がかかった。

| @技術/プログラミング

Capybara + Selenium でテストしていて、JavaScript の alert() の中身を調べたいとき、 ただ単に

it 'alert の中身は「うんこ」' do
  find('#unko').click
  page.driver.browser.switch_to.alert.text.should == 'うんこ'
end

とかやるだけでは Selenium::WebDriver::Error::UnhandledAlertError が発生する。

it 'alert の中身は「うんこ」' do
  find('#unko').click
  page.driver.browser.switch_to.alert.text.should == 'うんこ'
  page.driver.browser.switch_to.alert.accept
end

というように最後に OK ボタンを押す操作を追加してあげないといけない。

| @技術/プログラミング
[1] pry(2.0.0-p195)> require 'open-uri'
[2] pry(2.0.0-p195)> require 'active_support/core_ext/hash/conversions'
[3] pry(2.0.0-p195)> Hash.from_xml(open('http://www.portalshit.net/index.atom').read)
=> {"feed"=>
  {"xmlns"=>"http://www.w3.org/2005/Atom",
   "id"=>"http://www.portalshit.net/",
   "title"=>"portal shit!",
   "updated"=>"2013-06-18T19:07:44+09:00",
   "link"=>
    [{"type"=>"text/html",
      "rel"=>"alternate",
      "href"=>"http://www.portalshit.net/"},
     {"type"=>"application/atom+xml",
      "ref"=>"self",
      "href"=>"http://www.portalshit.net/index.atom"}],
   "entry"=>
    [{"id"=>"tag:www.portalshit.net,2013-06-18T19:04:33+09:00",
      "title"=>"Alfred で Chrome のブックマークを検索する",
      "published"=>"2013-06-18T19:04:33+09:00",
      "updated"=>"2013-06-18T19:07:44+09:00",
      "link"=>
       {"type"=>"html",
        "rel"=>"alternate",
        "href"=>
         "http://www.portalshit.net/2013/06/18/chrome-bookmark-search-with-alfred"},
      "content"=>
       "<p><img src=\"https://resources.portalshit.net/945-chrome-bookmark-search-with-alfred.png\" alt=\"945-chrome-bookmark-search-with-alfred.png (708×295)\
      "author"=>{"name"=>"morygonzalez"}},

で XML の内容を Hash にできる。ActiveSupport 便利。

| @技術/プログラミング

jQuery Validation で特定のイベントに対してだけバリデーションを無効にする方法が分からなくて困ってた。例えばフォームの中の送信ボタンではなくキャンセルボタンが押されたときにはバリデーションを行わずにフォームを送信したいということがあると思う。

調べていたら以下の記事がひっかかった。

input タグの class に "cancel" を指定すれば validate されないとある。ほかに、ボタンの click イベントとかで

$("form").validate().cancelSubmit = true;

と書いてやっても良いみたい。こちらは JavaScript で form を submit() するタイプのやつにも使えて使い勝手良さそう。

jQuery Validation 、便利だけどドキュメントが充実してなくてつらい。あとどれが公式か分からないのもつらい。去年くらいまで jQuery Plugin のサイトにドキュメントあった気がしたんだど今は別のサイトに単独で存在してる。

| @技術/プログラミング

Lokka を Ruby 2.0 で動かすために bundle update してたら newrelic_rpm.gem もアップデートされて、バージョンが 3.6.2.96 から 3.6.3.111 に上がった。Newrelic にはサーバーサイドのモニタリングとクライアントサイドのモニタリングがあるんだけど、Sinatra (一部 Padrino)で動いている Lokka に関してはクライアントサイドのモニタリング(Rack アプリケーションに JavaScript を埋め込んで JS とか HTML のパフォーマンスを調べるやつ)が動いてなかった。しかし最新バージョンでは Sinatra と Padrino をサポートした模様。

Newrelic 、まじでイノベーティブだなーと思いながら使ってるけど、クライアントの gem も頻繁に更新されてて本当にすごい。一般のウェブアプリケーションエンジニアがあったら便利だなーと思うものがオールインワンでセットになってる。最初に heroku を知ったときのような感動がある。Eat their own dog food してると思う。

| @技術/プログラミング

昨日、こういう Pull Request が Lokka に来てた。

「あれ、Lokka の master ブランチは Ruby 2.0 対応してないんじゃ」と思って Ruby 2.0.0-p0 で試してみたところ案の定 json.gem のインストールに失敗する。しかしものは試しにと思って、最新のパッチレベルの 2.0.0-p195 をインストールしてみたら Ruby 2.0 で Lokka 起動できた。

というわけでポータルシットは Ruby 2.0 で動いております。

| @技術/プログラミング

フッターのキャッシュとかフラグメントキャッシュはできたので、サイトのなかで一番重いアーカイブページのキャッシュを考えてみることにした。

当初はアーカイブページも、一番重い記事一覧表示部分をフラグメントキャッシュしてみていた。しかしあまり効果がなかった。Sinatra は仕組み上、コントローラーにいろいろ書いてしまいがちになり、アーカイブページのコントローラーが Fat になっていた。そのためフラグメントキャッシュをしたところでコントローラーの重い処理はビューがレンダリングされる前に走ってしまい、キャッシュの意味があまりない状態だった。

Rails だったらアクションキャッシュとかあるけど、先日から Folk して改造を進めている sinatra-cache でできるのはページキャッシュとフラグメントキャッシュだけなため、ページキャッシュをしてみることにした。

ページキャッシュの残念な点は Nginx 側の設定も必要なことだ。せっかく Lokka は Heroku や Sqale など Rack アプリケーション置ける PaaS にならどこにでも置けるのに、Nginx の設定変更を前提とした変更を行うと CMS for Cloud ではなくなってしまう。しかしこのブログは自分の勉強の場でもあるのでえいやっとやてみた。

sinatra-cache は Lokka + Nginx + Unicorn という環境であれば、LOKKA_ROOT/lib/lokka/app.rb を開いて以下のようにしてやれば使えるようになります。

require 'lokka'
require 'sinatra/cache'        # <= 追加

module Lokka
  class App < Sinatra::Base
    configure do
      # ...
      register Sinatra::Cache  # <= 追加
      set :cache_enabled, true # <= 追加
      # ...
    end
    # ...
  end
end

とかやってやれば、勝手に LOKKA_ROOT/public にキャッシュファイルを作るようになります。Nginx 側でキャッシュファイルがあれば Unicorn に proxy せずキャッシュファイルを返すようにすればページキャッシングで爆速になる。sinatra-cache は {$request_filename}.html という名前でキャッシュファイルを作るので Nginx の設定は以下のような感じになる。

server {
    location {
        root /var/wwww/portalshit/public;
        # ...
        if (!-f $request_filename.html) {
            add_header Cache-Control public;
            rewrite (.*) $1.html;
            break;
        }
        # ...
    }
}

ポータルシットはトップページも重いのでトップページもページキャッシュしようかなと思ったけど、ページングとかあるのでいろいろ面倒くさいことになることに気がついた(キャッシュファイルがない状態で Google のクローラーが 35 ページ目とかをクローリングしてたら 35 ページ目の html が index.html としてキャッシュされてトップページに来た人が全員 35 ページ目を見ることになってしまう)のでやめた。

キャッシュ、レスポンスを速くしてくれるけど何でもキャッシュすれば良いわけではないし奥が深い。