Read It Later の RSS にタイトルと本文つける Web サービスの裏側

このサービスは Heroku の上で Sinatra を動かしている。
Heroku + Sinatra の組み合わせが案外情報が少なかったので
シェアするためのエントリ。
Heroku + Sinatra + ActiveRecord (migrate) + cron な人の参考になるかも。



全ソースコードは
http://github.com/mallowlabs/read-it-later-rss に上げてある。
ライセンスは MIT Lisence で。

Heroku + Sinatra + ActiveRecord

まずはインストール
.gems に以下のように記述

sinatra
activerecord

この状態で push すれば gem が自動でインストールされる。便利!


Deploying Rack-based Apps | Heroku Dev Center を読むと

require 'activerecord'

dbconfig = YAML.load(File.read('config/database.yml'))
ActiveRecord::Base.establish_connection dbconfig['production']

と書けばよいと書いてあるが実際はこう。

require 'logger'
require 'active_record'
ActiveRecord::Base.logger = Logger.new(STDOUT)
dbconfig = YAML.load(File.read('config/database.yml'))
ActiveRecord::Base.establish_connection dbconfig['production']

active_record の "_" は入れないと警告が出る。
require のときは "_" を入れるけど、.gems には入れたらダメ。
また、Logger を設定しないと AR が走ったときにコケる。

Heroku + Sinatra + ActiveRecord (migrate)

普通に migrate ファイルを作る。
db/migrate/001_create_base.rb

class CreateBase < ActiveRecord::Migration
  def self.up
    create_table :pages do |t|
      t.text :url
      t.text :title
      t.text :content
      t.timestamps
    end
    add_index :pages, :url
  end

  def self.down
    remove_index :pages, :url
    drop_table :pages
  end
end

Rakefile に以下を追加。

namespace :db do
  desc "migrate database"
  task :migrate do
    ActiveRecord::Migrator.migrate('db/migrate',
          ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
  end
end


Sinatra アプリのどこかで以下を呼ぶ。
筆者の場合は lib/boot.rb

Dir::glob("#{File.dirname(__FILE__)}/models/*.rb") do |f|
  load f
end


Model 用クラスを作る。
lib/models/page.rb

class Page < ActiveRecord::Base
end


設定ファイルも忘れずに作る。
ただし、このファイルは Heroku 側に push してはいけない。
config/database.yml(.example)


ローカルの DB に反映する場合は Rails と一緒で

$ rake db:migrate

Heroku 側の DB に反映する場合には

$ heroku rake db:migrate

Web を調べると taps を使えという記述がみられるけど
テーブル作るだけなら上記コマンドで十分。
Heroku 上では config/database.yml が自動で作られて
PostgreSQL のデータベースを使うことができる。
config/database.yml を push してはダメというのはそういう意味。

Heroku + Sinatra + cron

まず大前提として

  • 無料プランでは daily cron しか使えない
  • daily cron を使うためにはクレジットカード情報の登録が必要

ということに注意。


Heroku Scheduler | Heroku Dev Center を読むと
cron タスクは environment に依存してるけど
Sinatra アプリにはそんなものはないので単純に削除。
Rakefile に以下を追加

task :cron do
  Page.delete_all(["created_at < ?", Time.now - 30.days])
end

Heroku の無料プランだと DB は 5MB しか使えないので
30日以上古いデータを削除するようにしている。


以下のコマンドで daily cron有効にする。

$ heroku addons:add cron:daily

cron を任意のタイミングで実行するには

$ heroku rake cron

cron の実行ログを見るには

$ heroku logs:cron


ハマりそうなポイントは以上。
わからない部分があったらソースを読んでください。