Rails4アプリケーションをherokuにdeploy ～ざっくり手順とハマり履歴

## 前提

 - gem heroku インストール済み
 - ssh key生成済み＆herokuへの登録済み

## 準備

### Gemfile
RailsTutorial 1.5.1を参考に以下を記述した。

```ruby:Gemfile
group :development, :test do
  # Use sqlite3 as the database for Active Record
  gem 'sqlite3'
end

group :production do
  gem 'pg'
  gem 'rails_12factor'
end
```

※[Rails5の場合、rails_12factorは不要。](https://github.com/heroku/rails_12factor)

### database.yml
こんな感じでOK。

```yaml:database.yml
:
production:
  adapter: postgresql
  encoding: unicode
  pool: 5
```

### assetsのprecompile

```bash
> bundle install --without production
> rake assets:clean
> rake assets:precompile
```

[assets:compileし直すときassets:cleanしておくとgitが自動でrenameしてくれて便利](http://blog.scimpr.com/2013/01/27/assetscompile%E3%81%97%E7%9B%B4%E3%81%99%E3%81%A8%E3%81%8Dassetsclean%E3%81%97%E3%81%A6%E3%81%8A%E3%81%8F%E3%81%A8git%E3%81%8C%E8%87%AA%E5%8B%95%E3%81%A7rename%E3%81%97%E3%81%A6%E3%81%8F%E3%82%8C/) とのこと。

古いのがたくさん溜まっている時は assets:clobber するとよい。

ここで、すべてgitにコミットし、
masterにmergeしておく。

### いよいよdeploy

```bash
> heroku login  ※未ログインの場合

> heroku create アプリケーション名（小文字+ハイフンのみ）
Creating app-name... done
https://app-name.herokuapp.com/ | https://git.heroku.com/app-name.git

★ここでエラーになったことがあった。ハマり履歴参照。

> git remote -v ※heroku が remote に追加されたことを確認
heroku  https://git.heroku.com/app-name.git (fetch)
heroku  https://git.heroku.com/app-name.git (push)
origin  git@github.com:xxx/app_name.git (fetch)
origin  git@github.com:xxx/app_name.git (push)

> git push heroku master

※Windows環境で開発している場合はGemfile.lockに関する警告が表示されるようだ。（2016/12/06現在）詳しくはハマり履歴参照。

> heroku run rake db:migrate   ★ここが鬼門！ハマり履歴参照。
```

以上で deploy は完了。

[mongodbを使う場合はこちら - Qiita](http://qiita.com/leon-joel/items/2f13172c904b8a14b109)


### アプリを開いてみる。ログ参照など。

コマンドラインからアプリをopen出来る。

```bash
> heroku open
```

最初はちゃんと動作しないことが多いので、ログをリアルタイムで参照したくなるはず。

```bash
> heroku logs --tail
```

## ハマり履歴

### Windows環境で生成したGemfile.lockに関する警告
Windows上でbundle installしたGemfile.lockをgit pushすると、以下の警告が表示される。（2016/12/06現在）
Herokuのドキュメントを読む限り、回避策は「Windows以外の環境でGemfile.lockを作成する」しかないようだ。

```
remote: ###### WARNING:
remote:        Removing `Gemfile.lock` because it was generated on Windows.
remote:        Bundler will do a full resolve so native gems are handled properly.
remote:        This may result in unexpected gem versions being used in your app.
remote:        In rare occasions Bundler may not be able to resolve your dependencies at all.
remote:        https://devcenter.heroku.com/articles/bundler-windows-gemfile
```

### heroku create でエラー

```bash
> heroku create xxx

heroku-cli: Installing CLI... 18.22MB/18.22MB !    Heroku client internal error.
 !    Search for help at: https://help.heroku.com
 !    Or report a bug at: https://github.com/heroku/heroku/issues/new

    Error:       Invalid argument - C:\Users\xxx\AppData\Local/heroku/cli/lib/cacert.pem (Errno::EINVAL)
    Command:     heroku create xxx
    Version:     heroku/toolbelt/3.43.14 (i386-mingw32) ruby/1.9.3
    Error ID:    xxx

    More information in C:/Users/xxx/.heroku/error.log
```

どうやら何かのバージョンが古かったようだ。heroku update すれば上手くいくようになった。

```bash
> heroku --version
heroku/toolbelt/3.43.14 (i386-mingw32) ruby/1.9.3
heroku-cli/5.5.5-789c5b7 (windows-386) go1.7.4
You have no installed plugins.

> heroku update
heroku-cli: Updating plugins... done

> heroku create xxx
Creating xxx... done
https://xxx.herokuapp.com/ | https://git.heroku.com/xxx.git
```

### 単数形複数形問題

| 単数形 | 複数形 |
|:------|:-------|
| base -> | -> bases |
| basis <- | <- bases |

base →複数形にすると→ bases →単数形にすると→ basis
つまり、元に戻らないということ。

これにより、ローカル（SQLite3）では上手くいっていた db:migrateが、heroku上（PostgreSQL）では上手くいかなくなった。

単複問題が発生しないようModel（とMigration）をガッツリ修正し、git pushし、

```
heroku run rake db:migrate  ☆migrationをいろいろやったせいか、何かエラーがでた…

heroku run rake db:setup  ☆permissionがどうのこうのとエラーが出た

heroku restart  ☆仕方ないのでrestartしてみたら、うまくいくようになった

heroku run rake db:migrate
heroku run rake db:fixtures:load
```

### heroku run rake db:migrate で PG::UndefinedColumn エラー

```
Running rake db:migrate on app-name... up, run.4549
== 20160527132600 CreateBlogs: migrating ======================================
-- create_table(:blogs)
   -> 0.0129s
-- change_table(:entries)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::UndefinedColumn: ERROR:  column "blog_id" referenced in foreign key constraint does not exist
: ALTER TABLE "entries" ADD CONSTRAINT "fk_rails_1c7d1d2722"
FOREIGN KEY ("blog_id")
  REFERENCES "blogs" ("id")
```

何度やっても同じエラーが発生。

仕方ないのでダメ元で ```heroku run rake db:setup```やってみたら、いくつかのエラーが出たものの、migrationはなぜか成功。

```
> heroku run rake db:setup
:
Running rake db:setup on app-name... up, run.2749
FATAL:  permission denied for database "postgres"
DETAIL:  User does not have CONNECT privilege.
:
Couldn't create database for {"adapter"=>"postgresql", ...}
:
-- create_table("blogs", {:force=>:cascade})
   -> 0.0380s
:
-- add_foreign_key("entries", "blogs")
   -> 0.0027s
-- initialize_schema_migrations_table()
   -> 0.0158s

> heroku run rake db:migrate  ※確認のために再度実行
Running rake db:migrate on app-name... up, run.5829
```

### ブラウザでアプリケーションにアクセスしたら ```secret_token and secret_key_base```がないというInternal Server Errorが

```
Internal Server Error
Missing `secret_token` and `secret_key_base` for 'production' environment, set these values in `config/secrets.yml` 
```

secrets.yml がgitに入っていなかった。
まずは環境変数 SECRET_KEY_BASE を参照するように記述されていることを確認。

```yaml:secrets.yml
production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
```

その上で、.gitignore から外して、git add&commit&push でOK！

## よく使うHerokuコマンドなど

#### ログをtail表示

```bash
> heroku logs --tail
```

#### Heroku無料で使える残り時間を確認

[Herokuを無料で使えるのは1000時間/月まで（但し、クレジットカート登録した場合）](https://devcenter.heroku.com/articles/free-dyno-hour-faq#how-many-free-dyno-hours-will-i-receive)なので、残り時間が気になる場合は[以下のコマンド](https://devcenter.heroku.com/articles/free-dyno-hour-faq#how-will-i-know-what-my-current-quota-is-and-how-much-of-it-i-have-used)
で確認できる。

```bash
> heroku ps --remote heroku
Free dyno hours quota remaining this month: 904h 50m (90%)

> heroku ps --app xxx
（出力は上と同じ）
```

もしくは、Herokuダッシュボード（WEB）の、Account Settings ⇒ Billing から。各 Dyno の消費時間を一覧できる。


## その他メモ
[知っておきたい！Herokuを使う上では当たり前？の16の常識](http://blog.mah-lab.com/2013/05/16/heroku-commons-16/)
[バックグラウンドジョブの改善によってRailsのパフォーマンスを高める]
(http://postd.cc/improving-rails-scalability-with-better-architecture/)
[アドオン mLab mongodbを使う手順 - Qiita](http://qiita.com/leon-joel/items/2f13172c904b8a14b109)