Herokuの操作覚書（Railsを中心に）

#0. はじめに
仕事でherokuを使うことは全くないのですが、プライベートで作ったリポジトリを外部に公開するときは、Railsプロジェクトであればherokuを使うのはとても手っ取り早い良い方法だと思います。
仕事で使っていない以上、年に数回しかherokuに触ることなく、その度ごとにheroku固有のやり方やコマンドを忘れてしまうので、まとめていきたいと思います。
逐次追記する予定です。

#1. herokuでRailsを使いつつ、デプロイ時にトランスパイルする
私が作るRailsプロジェクトの多くは、frontendディレクトリを持ち、その中はfrontendの世界観で構成されており、webpackを使ってbabel等でトランスパイルしたファイルをapp/assets配下に吐き出し、sproketsで呼び出すというやり方をすることが多いです。
この辺りは以前一緒に働いていた方の[こちらの記事](https://qiita.com/necojackarc/items/afa674ab10aafa9784eb)をご参照ください。

仕事では、様々な事情から、トランスパイルしたファイルをgitに追加して運用しているのですが、自動生成されたファイルをcommitするのはよろしくないという思いがあるので、プライベートで作っているプロジェクトでは、トランスパイルしたファイルはcommitに含めていません。
当然ながら、.gitignoreにはapp/assets配下は除くように設定してあります。

```:.gitignore
/app/assets/javascripts/*
```
このような状況の中で、herokuにdeploy時にwebpackのコマンドも実行してあげる方法を記述します。

今回のRailsプロジェクトのディレクトリ構成は、

```
.
├── Gemfile
├── （省略）
├── app
├── frontend
│   └── package.json -> ../package.json （symbolic link)
└─ package.json
```
となっており、普段は、frontendディレクトリ下で`npm run watch`や`yarn watch`を実行して開発を行うことが多いです。
`package.json`は当初は、frontend配下に置いていたのですが、herokuのnodeのbuildpacksではリポジトリ直下の`package.json`を見に行くようなので、リポジトリ直下に`package.json`を置き、frontendディレクトリ直下にはリポジトリ直下の`package.json`に対してシンボリックリンクを貼るような形にしています。

デプロイ後に`npm run release`を実行するために、package.jsonの`heroku-postbuild`を追加します。このスクリプトは、herokuのbuildpacks（後述）のnodejsのところで実行されます。`cd ../`コマンドなどはもしかしたら不要かもしれません。

```json
"scripts": {
  "release": "webpack --mode production --config webpack.config.js",
  "watch": "webpack --mode development --watch --config webpack.config.js",
  "heroku-postbuild": "cd frontend; npm run release; cd ../"
}
```
herokuには、buildpacksというものがあり、rubyを選んだ場合は、rubyしかないはずです。`heroku buildpacks`コマンドで確認できます。

```sh
$ heroku buildpacks
=== your-app-name Buildpack URLs
1. heroku/ruby
```
今回はnode.jsも使用したいため、buildpackを追加します。

```sh
heroku buildpacks:add --index 1 https://github.com/heroku/heroku-buildpack-nodejs
```
ここで注意は、`--index 1`とすることです。これを忘れると、デプロイ後、アクセス時に`npm start`が走ってしまい、エラーとなります。
このコマンド実行後の`buildpacks`は以下のようになると思います。

```
$ heroku buildpacks
=== your-app-name Buildpack URLs
1. https://github.com/heroku/heroku-buildpack-nodejs
2. heroku/ruby
```
これで通常通り`git push heroku master`などとすればdeploy時にまず`npm run release`コマンドが走り、app/assets配下にファイルを置いてくれます。
その後、railsのdeployが始まり、その中で、assets:precompileが行われ、ここから先はsproketsの世界になります。
sproketsが嫌な方はuglifyやダイジェストの付与等もwebpackにやってもらうような設定にしても良いかと思います。

#2. postgisを入れる。
地理除法をPostgreSQL上で扱うために使われるのがpostgisです。これのheroku上での利用方法について記載します。
まずは、buildpackを追加します。

```bash
heroku buildpacks:add --index 2 https://github.com/cyberdelia/heroku-geo-buildpack.giat
```

herokuのpostgresqlに接続（接続方法は下記の「よく使うコマンド」参照）し、EXTENSIONを作成します。

```
CREATE EXTENSION postgis;
```

このままだと、migrationする際に怒られます。

```
undefined method `st_point' for #<ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition:0x00000004ab9ab0>
```
herokuの中の環境変数の`DATABASE_URL`を書き換える必要があります。（[参照](https://devcenter.heroku.com/articles/rails-database-connection-behavior#active-record-4-1-escape-valve)）

```yml:database.yml
default: &default
  adapter: postgis

production:
  <<: *default
  url: <%= ENV.fetch('DATABASE_URL', '').sub(/^postgres/, "postgis") %>
```
最後にmigrationの実行しカラムを追加します。

```bash
heroku run rake db:migrate
```

#2. postgresqlのデータをバックアップする
完全にコマンドのメモです。

既存のバックアップファイルの確認。バックアップを一度も実行したことない場合はNo backups found.などと出るはずです。

```bash
$ heroku pg:backups --app your-app-name
# --app your-app-name は -a your-app-name と同じ意味。

=== Backups
ID    Created at                 Status                               Size     Database
────  ─────────────────────────  ───────────────────────────────────  ───────  ────────
b002  2018-03-10 14:22:16 +0000  Completed 2018-03-10 14:22:17 +0000  39.41kB  DATABASE
b001  2018-03-09 15:26:41 +0000  Completed 2018-03-09 15:26:42 +0000  34.71kB  DATABASE

=== Restores
No restores found. Use heroku pg:backups:restore to restore a backup

=== Copies
No copies found. Use heroku pg:copy to copy a database to another
```

バックアップを行います。

```bash
$ heroku pg:backups:capture --app your-app-name

Starting backup of postgresql-pointy-60299... done

Use Ctrl-C at any time to stop monitoring progress; the backup will continue running.
Use heroku pg:backups:info to check progress.
Stop a running backup with heroku pg:backups:cancel.

Backing up DATABASE to b001... done
```
これを行なった後、再度`heroku pg:backups --app your-app-name`を実行すれば、Backupsのところに表示されるはずです。IDのところが大事です。

バックアップファイルをlocalに持ってくる方法になります。Macユーザーでcurlが入っていない場合は、homebrewなどでinstallしてください。publick-urlのあとのb001の箇所は前述のIDのところ値を入れます。

```bash
$ curl -o `date "+%Y%m%d%H%M%S"`.dump $(heroku pg:backups public-url b001 --app your-app-name)
```

バックアップしたファイルでlocalのpostgresqlにリストアします。ファイル名はcurlしたときに保存されたファイル名を指定します。

```bash
$ pg_restore --verbose --clean --no-acl --no-owner -h localhost -d your_database_name 20180101000000.dump
```

## よく使うコマンド
- sshする

```bash
$ heroku run bash
```
- 直接rails consoleに行きたい場合

```bash
$ heroku run console
```
- migrationを実行する

```bash
heroku run rake db:migrate
```
- databaseに接続したい場合

```bash
$ heroku run console
```
でrails consoleに入り、

```ruby
config = ActiveRecord::Base.configurations[Rails.env] || Rails.application.config.database_configuration[Rails.env]
```
にて、`password`を調べる。

```bash
$ heroku run bash
$ rails db
Password: # ↑で調べたpasswordを入力
```