怖話でエラー画面の文言を何とか仕様の日本語訳として全くの間違いとは言い切れないぐらいの範囲で怖いものにできないか挑戦してみた。

404

あなたの要求された対象が計算機上に存在しません。もしくは故意に要求を処理していませんが、その理由を明かせません。または何らかの未知の現象が発生しました。

404 Not Found - 怖話 | 怖い話がスマホでも

406

あなたの要求する種類の媒体を受け入れることができません。

406 Not Acceptable - 怖話 | 怖い話がスマホでも

422

あなたの要求に同封される構成要素が処理できない、もしくは理解できません。

422 Unprocessable Entity - 怖話 | 怖い話がスマホでも

500

計算機内部であなたの要求を妨げる予期しない原因不明の状態が発生しました。

500 Internal Server Error - 怖話 | 怖い話がスマホでも

production環境ではexception_notificationでエラーをメールしてる人も多い思います。(AirBreakとかも)

怖話でもそうやってエラーメールが一通も来ない状態にしたいんですが、例えば下記のような”バグじゃないエラー”は皆様どうやって対応してるんでしょう?

A ActionView::MissingTemplate occurred in home#index:

 Missing template home/index, application/index with {:handlers=>[:erb, :builder, :haml], :formats=>["*/*;q=0.01"], :locale=>[:ja, :ja]}. Searched

formatsに*/*;q=0.01なんて文字列を送ってくるのは単なるスパム。使ってるformatだけに限定するように何か書く?うーん・・・。

怖話.jpをHerokuからさくらVPS 512に移行することにしました。理由は下記です。

  • DB容量が無料の範囲を大幅に超えている。(一応容量オーバーしていても使える)
  • slug(リポジトリ)のサイズが制限(100MB)を超えた。(これはオーバーしているとpushできない)
  • ファイルアップロードが必要になった。(S3を使えば対応は可能)
  • 回線が遅い。(us westとかなので仕方が無い)

Amazon EC2にしなかった理由はまだ人気が無いのでお金をかけられないからです。もし売上が月数十万になったら移行します。

DB移行

HerokuのDBはPostgreSQLです。さくらVPS 512ではMySQLを使うことにしました。

現在のDB容量は37.4MB。レコード数は約2万件ぐらいです。heroku db:pullをしたら1時間たっても終わる気配がなかったので次の方法を取ることにしました。

  • herokuからローカルにpg_dumpを持ってくる。
  • ローカルのpostgresにpg_restore。
  • ローカルのmysqlにtapsサーバーを立てる。
  • ローカルのpostgresからtapsサーバーへpush。
  • ローカルのmysqlからmysqldump。
  • さくらVPSのmysqlにrestore。

大したデータ量じゃないのに、要はネット経由でtapsするととてつもなく時間がかかるのです。

「これ絶対もっと楽な方法あるよなあ」

などと思いながら作業しました。

怖話.jpのランキングの実装を考える。(ニコニコ動画で言えば総合ランキング)

下記の様に各怖い話のスコアを算出してそれでソートする。

スコア = PV数 + 怖いの数 * 1000 + コメント数 * 100

("怖いの数"というのはニコニコ動画で言えば"マイリスト数")

当分の間、特殊なランキングアルゴリズムは必要無いだろう。1000と100という重みは定数にして様子を見ながら変えていく。

人気サイトであれば裏で集計すべきだけどまだ貧弱サイトなので毎回サブクエリで集計してしまおう。

select * from stories order by view + (select count(*) from scares where scares.story_id = stories.id) * 1000 + (select count(*) from comments where comments.story_id = stories.id) * 100 desc, id desc;

我ながらとっても遅そうなクエリだ。

class Story < ActiveRecord::Base
  scope :order_by_ranking, order("view + (select count(*) from scares where scares.story_id = stories.id) * #{Scare::RANKING_WEIGHT} + (select count(*) from comments where comments.story_id = stories.id) * #{Comment::RANKING_WEIGHT} desc, stories.id desc")
end
Story.order_by_ranking.page(params[:page]).per(50)

ActiveRecordとkaminariのお陰でスマートな見た目にできたが、気をつけて実行しなければならない重いsocpeになってしまった。