まえ作った Amazonの検索結果が新規ウィンドウで開かれるのを殺すユーザースクリプト が Amazon の HTML 変更により動かなくなってたので更新した。Amazon 見てたら無限に新しいタブが開いていく現象にお困りの方はご利用ください。
Syntax Highlight Plugin で Ajax をやめた
Lokka で Syntax Highlight するプラグイン(morygonzalez/lokka-pygmentize · GitHub)、これまで Ajax で Syntax Highlight させてたんだけど、HTTP リクエストが増えていけてないと感じたのでサーバーサイドでハイライトが完結するように変更した。Railscasts の #272 Markdown with Redcarpet - RailsCasts を参考にして、プラグインの中で Entry クラスを再オープンした。こんな感じ。
class Entry
  def body
    doc  = Nokogiri::HTML(self.long_body)
    doc.search("//pre").each do |pre|
      code = pre.css("code")[0]
      pre.replace Pygments.highlight(
        code.text.rstrip,
        :lexer   => code[:class],
        :options => { :encoding => 'utf-8' }
      )
    end
    doc.to_s
  end
end前の実装はだいぶいけてなかったと思うので随分マシになったと思う。あと この Pull Request でレンダリングエンジンに Redcarpet が追加されたので、GitHub と同じように
```ruby ```
みたいな感じの書き方でコードがハイライトされるようになった。便利。
追記1
ちゃんと動いてなかった…。夜直します…
追記2 2013/02/04 0:45
最終的にオープンした Entry クラスのコードは以下のようになった。
class Entry
  alias_method :original_long_body, :body
  def highlighted_long_body
    syntax_highlight(self.original_long_body)
  end
  alias_method :body, :highlighted_long_body
  alias_method :original_short_body, :short_body
  def highlighted_short_body
    syntax_highlight(self.original_short_body)
  end
  alias_method :short_body, :highlighted_short_body
  def syntax_highlight(body)
    doc = Nokogiri::HTML(body)
    doc.search("//pre").each do |pre|
      code  = pre.css("code")[0]
      lexer = if pre[:class].present?
                pre[:class]
              elsif code.present? && code[:class].present?
                code[:class]
              else
                nil
              end
      begin
        pre.replace Pygments.highlight(
          code.text.rstrip,
          :lexer   => lexer,
          :options => { :encoding => 'utf-8' }
        ) if code
      rescue MentosError
        next
      end
    end
    doc.to_s
  end
endLokka、結構メタプログラミングが多くて、Entry クラスのインスタンスの body メソッドは単なるゲッターではなく、 index アクションのときと show アクションのときで別々にエイリアスが設定されていて、index アクションのときは Entry#short_body 、show アクションのときは Entry#long_body が呼ばれるようになっていた。アラウンドエイリアス使って力業で解決したけど他のプラグインが同じように振る舞ったら破滅を招きそうな気がする…。それにしても『メタプログラミング Ruby』読んでなかったらどうすればいいか皆目検討付かなかっただろうなー。
Unicorn が暴走して困ってる
最近、cap deploy がしんどい。

こんな感じで、デプロイすると CPU の使用率が高まってしまう。Unicorn が暴走してるっぽい。シンボリックリンクとかはちゃんと置き換わってるんだけど、プロセスが古いままで、サイトの出力が新しくデプロイしたものに置き換わらない。こうなると cap deploy:restart とかやっても無反応で、ssh でログインして Unicorn を一旦停止し、手動で Lokka を再起動しないといけない。
拡散お願いしますアドベントカレンダー2012 に参加したとき、記事を公開してすぐサイトが落ちてしまって「やっぱりスモールマイクロインスタンスでは人気サイトポータルシットを運用するのは無理なのかな」と思ったのだけどどうもアクセスが集中して落ちたわけではないっぽい。
何なんだろう。
Lokka で過去記事一覧を表示するプラグインを作った
P_BLOG 使ってた頃から過去記事タイトルを一覧表示する機能は自分で自分の記事を読み返すときに重宝していて、この機能が欲しかったので作った。過去記事を全部一覧表示すると重いので一年分ずつ表示するようにした。便利。
ソースコードは以下。
ちなみにテストはありません。悪しからず。
SQL 力の弱まり
一個前の記事で書いた「記事の更新時に updated_at ではなく created_at が更新されてしまう」問題、原因はプログラム側にあるのではなく、MySQL の設定の問題だった。
mysql> desc entries;
+-----------------+--------------+------+-----+---------------------+-----------------------------+
| Field           | Type         | Null | Key | Default             | Extra                       |
+-----------------+--------------+------+-----+---------------------+-----------------------------+
| id              | int(11)      | NO   | PRI | NULL                | auto_increment              |
| user_id         | int(11)      | YES  |     | NULL                |                             |
| category_id     | int(11)      | YES  |     | NULL                |                             |
| slug            | varchar(255) | YES  |     | NULL                |                             |
| title           | varchar(255) | YES  |     | NULL                |                             |
| body            | text         | YES  |     | NULL                |                             |
| type            | text         | NO   |     | NULL                |                             |
| draft           | tinyint(1)   | YES  |     | 0                   |                             |
| created_at      | timestamp    | NO   |     | CURRENT_TIMESTAMP   | on update CURRENT_TIMESTAMP |
| updated_at      | timestamp    | NO   |     | 0000-00-00 00:00:00 |                             |
| frozen_tag_list | text         | YES  |     | NULL                |                             |
| markup          | varchar(255) | YES  |     | NULL                |                             |
+-----------------+--------------+------+-----+---------------------+-----------------------------+
12 rows in set (0.00 sec)updated_at と created_at の設定値が逆になってたのが原因。ALTER 文でカラムの情報を入れ替えておいた。
MySQL に流し込んだ Sqlite3 のデータを dump したやつの CREATE TABLE entries を見ると以下のようになってた。
CREATE TABLE `entries` (`id` integer PRIMARY KEY AUTO_INCREMENT, `user_id` integer, `category_id` integer, `slug` varchar(255), `title` varchar(255), `body` text, `type` text NOT NULL, `draft` boolean DEFAULT '0', `created_at` timestamp, `updated_at` timestamp, `frozen_tag_list` text, `markup` VARCHAR(255));なんでこれが created_at に対して更新時に現在時間を上書きし、 updated_at は作成時のみ現在時刻が入るようになるのかは分からない。
それにしても日頃 MongoDB ばかり使っていて、データにおかしなことがあるのはほぼ間違いなくコードのせいだと思う癖がついていることが今回よくわかった。データベースのスキーマを見てみるまでに3日くらい時間がかかった。とほほ。
一方でデータベース内のデータ構造のことをあまり考えなくてよく、開発のみに集中すればよい MongoDB はやっぱり便利だなと思った。規模がでかくなったり高速な読み書きをさばかなければならない状況だと MongoDB にも色々問題があるのでしょうけどね。
MySQL に変えた
Lokka 、データベースはずっと SQLite で使ってたけど仕事で MongoDB を使っているため SQL 力の弱まりを感じてきたので MySQL に変えてみた。SQLite3 から MySQL への移行は意外と面倒くさくて、以下の Redmine の手順を参考にやってみた。
- Strip out PRAGMA lines
- Strip out BEGIN TRANSACTION; lines
- Strip out COMMIT; lines
- Strip out DELETE FROM and INSERT INTO the sqlite_sequence table
- Replace AUTOINCREMENT with AUTO_INCREMENT
- Replace DEFAULT ‘t’ and DEFAULT ‘f’ with DEFAULT ‘1’ and DEFAULT ‘0’
- Replace ,’t’ and ,’f’ with ,’1’ and ,’0’
- Replace “ with ` except in string values (otherwise it replaces all quotes in your text)
↑の通りにやっておおむねうまくいったんだけど、なんか過去の記事を編集して更新すると、updated_at カラムだけじゃなく created_at まで更新されてしまうっぽい。SQLite で使ってるときにはそんなことなかったんだけどなぁ。これは問題な気がする。DataMapper のバグかな。土日で余裕があったら調べてみる。
Jekins でテスト結果のグラフが表示できなかった
VM 上の Scientific Linux で Jenkins を動かしていて、テスト結果のグラフが表示できない問題に遭遇していた。出るエラーメッセージは以下のようなもの。
Graphics N/A
Unable to access X. You need to run the web container in the headless
mode. Add -Djava.awt.headless=true to VM.OpenJDK が原因らしい(jenkinsでGraphics N/Aが出た時にしたこと | ミラボ)。
OpenJDK をやめて Oracle の JDK に変えればいいらしいのだけど、 OpenJDK でもグラフ表示できている人はいるっぽいし、ソースから Java を入れるのが嫌なので OpenJDK で何とかする方法を探していた。
もろもろ情報をあさってみたところ、どうもフォントがないのが問題らしい。
Jenkins の wiki にあるとおりに /var/log/jenkins/jenkins.log を漁ってみたら、以下のようなエラーメッセージを発見した。
Caused by: java.lang.Error: Probable fatal error:No fonts found.これに対して公式 wiki には
Obviously graphics rendering needs access to font metrics. So check java /etc/java-6-openjdk/fontconfig.properties and install missing fonts. OpenJDK refers to DejaVu-Fonts. So type:
sudo apt-get install ttf-dejavu
とあるので、yum search dejavu して dejavu って名前がついてるフォントを片っ端から入れたらちゃんとグラフが表示されるようになった。
お困りの方はお試しください。
 
      