heroku+sinatra+activerecord+postgresql

ローカルでの準備

環境

  • Vigrant with CentOS6.4
  • ruby 2.0~
  • postgresql9.3

postgresql のインストール

"PostgreSQL Deep Dive: VagrantPostgreSQL 9.3の動く仮想サーバを自動構築してみる (http://pgsqldeepdive.blogspot.jp/2013/09/vagrant-postgresql93.html)"のとおりにインストール。

データベースの作成

使用する database を作ります。

% sudo -u postgres -i
$ psql
=# create database testdb;
=#  \q

次にtableを postgresql で作ります。データベースは .env で指定し、model.rb でdotenv gem を使って読み込ませます。

% vi .env
DATABASE_URL = "postgres://localhost/testdb"

% vi model.rb
require 'dotenv'
require 'active_record'

Dotenv.load
ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'])

class Post < ActiveRecord::Base; end

Rakefileではそれを require します:

% vi Rakefile
require 'sinatra/activerecord'
require 'sinatra/activerecord/rake'
require 'rake/clean'

require './model'

migration ファイルを作り、migrate をかけテーブルを作成します:

% rake db:create_migration NAME=create_posts
....

% vi db/migration/xxxxx_create_posts.rb
class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
      t.string :text
      t.timestamps
    end
  end
end
% rake db:migrate
...

これでローカル上のデータベース作成は完了。念のため確認します:

% psql testdb
testdb=> \dt
              List of relations
 Schema |       Name        | Type  |  Owner
--------+-------------------+-------+---------
 public | posts             | table | vagrant
 public | schema_migrations | table | vagrant
(2 rows)

=> select * from posts;
 id |   text   |         created_at         |         updated_at
----+----------+----------------------------+----------------------------
=> \q

ウェブアプリの作成

'localhost:port/' にアクセスされると text: "hoge" なレコードを一つ追加していく簡単なsinatraアプリを作ります。

まずGemfile に使う gem を羅列し、bundler install して Gemfile.lock を作ります。

% vi Gemfile
source 'https://rubygems.org'

gem 'rake'
gem 'sinatra'
gem 'sinatra-contrib'
gem 'sinatra-activerecord', :require => 'sinatra/activerecord'

gem 'dotenv'
gem 'activerecord'
gem 'pg'

% bundle install
...

アプリ本体。こちらをまず先に require 'xxx' 形式で書いてから Gemfile に構成しなおしてもかまいません。

% vi app.rb
require 'bundler'
Bundler.require

require './model'

class MyApp < Sinatra::Base
  configure :development do
    register Sinatra::Reloader
    set :bind, '0.0.0.0'
  end

  get '/' do
    Post.create(text: "hoge")
    erb :show
  end
end
__END__
@@show
count: <%=  Post.count.to_s %>
<div>
<% Post.all.each do |post| %>
  <%= post.text %><br>
<% end %>

後は普通に config.ru を書き、rackup し、ブラウザ等で確認します:

% vi config.ru
require './app'
run MyApp

% bundle exec rackup &
....
% lynx losthost:9292

foreman 起動用ファイルの作成

% vi Procfile
web: bundle exec rackup -p $PORT

% foreman start &
17:38:52 web.1  | started with pid 3530
....
% curl losthost:5000

サーバーへのデプロイ

バックアップファイルなどをキレイにするため rake clean をかけ、 また.env はサーバー上に置くと変なことになるので gitignore しときます。

% rake clean
% vi .gitignore
.env

いつもどおりに:

% git init; git add . ; git commit -m init -a
% heroku create NAME
...

heroku-postgresql の addon を使います。後は通常の手順です。

%  heroku addons:add heroku-postgresql
...
%  heroku run rake db:migrate
...
% git push heroku master
...
% heroku ps
web.1: up 2014/MM/DD xx:xx:xx (~ 1m ago)

% heroku open
....

Tips

restart

データベースをrollback, migrate したりすると停止したりするので restart をかけます。

% heroku ps:restart web
Restarting web dynos... done

ローカルからサーバーのデータベースにアクセス

% heroku config して表示される DATABASE_URL の値を .env に入れます。

% heroku config
DATABASE_URL:               postgres://xxxuser:xxxpassword@@ecxxx.compute-x.amazonaws.com:5432/xxxdatabasename
HEROKU_POSTGRESQL_XXXX_URL: postgres://xxxuser:xxxpassword@@ecxxx.compute-x.amazonaws.com:5432/xxxdatabasename
LANG:                       en_US.UTF-8
RACK_ENV:                   production

% vi .env
#DATABASE_URL = "postgres://localhost/testdb"
DATABASE_URL = "postgres://xxxuser:xxxpassword@@ecxxx.compute-x.amazonaws.com:5432/xxxdatabasename"

参考