Sinatra-ActiverecordをHerokuにPushする


sinatra/activerecordを使ってDB操作するプログラムをHerokuへアップロードする際のメモ。
Herokuでアカウントを作っていることが前提。

## Herokuの設定
まず、Herokuにpostgresqlをアドオンする。
Herokuのマイページにログインして、「Add-ons」タブをクリックして、`Heroku Postgres`を選択するとアドオンできる。Hobby Devプランだと無料で20コネクション、1万行まで利用できる。
アドオンすると、`HEROKU_POSTGRESQL_(COLOR)_URL`というデータベース名(ショートカット名)が割り当てられる。

ちなみにローカルマシンの端末から下記コマンドでもアドオンできる。

    $ heroku addons:add heroku-postgresql
    ...
    Attached as HEROKU_POSTGRESQL_YELLOW_URL
    Database has been created and is available
    ....

次に、Herokuでは、`HEROKU_POSTGRESQL_(COLOR)_URL`を`DATABASE_URL`にマッチングすることを推奨しているので、その通りにする。コマンドは以下。

    $ heroku pg:promote HEROKU_POSTGRESQL_(COLOR)_URL

これで、一旦HerokuのPostgresqlの設定を確認する。

    $ heroku config
    === herokuapp Config Vars
    DATABASE_URL:	                postgres://〜
    HEROKU_POSTGRESQL_(COLOR)_URL: postgres://〜
    ....

となっていればOK。
ちなみに、postgresのURLの意味は
    
    postgres://username:password@host:port/databasename


## DBの接続設定とマイグレーション設定
Activerecordを使って、DBの接続設定を行い、マイグレーションしてDBテーブルを作成する。
事前に`$bundle exec rake db:create_migration`でマイグレーション用ファイルを生成しておきましょう。

まず、Activerecordの接続設定を行う。先ほど設定して`DATABASE_URL`を使う。ローカルの開発環境のDB接続設定も合わせてURL表記にして、||でつなげておく。
もしくは、ローカル環境の環境変数にも`DATABASE_URL`を設定しておいてもよい。

```ActiverecordのDB接続設定(ローカルでsqlite3を使う場合)
ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'] || 'sqlite3://localhost/***.db')
```

```ActiverecordのDB接続設定(ローカルでpostgresを使う場合)
ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'] || 'postgresql://username:password@localhost:5432/databasename')
```

```ActiverecordのDB接続設定(ローカルでもenvにDATABASE_URLを設定する場合)
require 'dotenv'  # .envファイルを読み込めるgem
Dotenv.load
ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'])
```

HerokuはDB接続を自動でコネクションを切断しないため、数回（5回？）のアクセスで、`ActiveRecord::ConnectionTimeoutError`が発生して、`Internal Server Error`となる。ソース内でconnectionを切断するように設定する必要あり。ひとまず、config.ruに`ActiveRecord::ConnectionAdapters::ConnectionManagement`を読み込ませておくと解決する。詳細は勉強中です。

```config.ru
require './app'

use ActiveRecord::ConnectionAdapters::ConnectionManagement

run Sinatra::Application
```

## HerokuへのアップロードとDBマイグレーション
ここまでできたら、Herokuへアップロード。その前に、`.gitignore`にアップロードしないファイルを記述しておく。
最低限以下３つは書いておくと良い。

```.gitignore
/vendor/bundle
/.DS_Store
/.env
```

    $ git add .
    $ git commit -m 'comment'
    $ git push heroku master

アップロードしたら、HerokuのDBをマイグレーションする。

    $ heroku run bundle exec rake db:migrate

これでOK。マイグレーションには、`sinatra/activerecord/rake`を使うので、`bundle exec `を指定しないとエラーとなる。

## 注意点（ハマったこと）

- 最初は`database.yml`を使おうとしたが、どうやらHerokuでは、`database.yml`を自動で生成するらしく、手動設定しても意味が無いみたい。結局、URL指定のやり方しかできなかった。

- Heroku上でのマイグレーションは、ちゃんと`bundle exec`しましょう。

- ローカル環境では、ActiveRecordのコネクションを自動切断してくれるが、heroku-postgresは自動切断してくれない。自分でコネクション切断処理を書かないとダメ。これに一番ハマった！！

- pushと同時に`bundle install`をするらしく、gemのバージョンを揃えるには`Gemfile`にバージョンもちゃんと指定しておく必要あり。

- `.gitignore`は、一度commitしたものには反映されないので、一旦`$git rm --cached `しておく必要あり。gitで管理しているファイル一覧を見るコマンド`$git ls-files`で内容を確認しましょう。

- テーブルを作り直す場合は、一旦DBを消去する必要あり。
    
         $ $heroku pg:reset DATABASE_URL --confirm app

- Herokuでは`sinatra/reloader`が使えない。当たり前ではあるが。
ローカルでは利用したいので、以下のようにしてみた。

```
if(ENV['RACK_ENV']=='development')
  require 'sinatra/reloader'
end
```

## その他
Herokuでよく使うコマンド。

- Herokuのタイムゾーンを東京にする。

        $ heroku config:add TZ=Asia/Tokyo

- Herokuのログを見る。

        $ heroku logs


## お世話になったサイト
- Heroku Dev Center
https://devcenter.heroku.com/articles/heroku-postgresql

- Sinatra×HerokuのDB設定をいい感じにする。
http://blog.notsobad.jp/post/60131290938/sinatra-heroku-db

- 公開したくない情報はdotenvにしまってしまう
http://shuzo-kino.hateblo.jp/entry/2014/04/15/225517

- herokuのデータベースをリセット/リストア/再構築する
http://qiita.com/quattro_4/items/a2eb3618207e21ca00d3

- "Deprecation warning: Database connections will not be closed automatically" #59
https://github.com/puma/puma/issues/59