Herokuでsinatraアプリを公開する手順

# 目的
sinatraからのHerokuへの公開時、最初によく使いそうな基本的な操作と知識をまとめる

# 前提

- Mac High Sierra
 - windowsでやる場合はvagrant上で
- ruby 2.4.1 (rubyが入っていない場合は、下部参照を確認) (バージョンが変わらない場合は、下部参照を確認)
- sqlite3 3.19.3
- postgres (PostgreSQL) 10.4
- sinatraアプリがすでにできていることを想定
 - ***起動ファイルは　heroku_study.rb***
  
> Sinatraの導入 
    https://qiita.com/yukihigasi/items/ffce19609ad8d935b7b0
> sinatraでアプリを作る 
   https://qiita.com/yukihigasi/items/284418046b8aac55d05b

# 手順
## アプリの修正
- アプリケーションの内容自体は問わないが、本手順作成では、先日の「sinatraでアプリを作る」のアプリをベースに、ルーティングを行なっていた起動時に呼び出す`sitatra_study.rb`というファイルを`heroku_study.rb`に名称変更している
- Herokuはsqlite3に対応していないため、本番環境ではPostgreSQLを使う、という定義を追加し、postgresqlをインストールしておく

- 端末にposgtresqlをインストール（macの場合）

```
brew install postgresql
```

- gemをインストール

```
sudo gem install pg -v '0.18.2'
```

## Herokuへのログイン
- CLIの導入
 - ログイン後、以下のページで言語を選択、rubyを選択する
![スクリーンショット 2018-07-17 20.58.31.png](https://qiita-image-store.s3.amazonaws.com/0/57455/279e40bb-112d-6fe3-f725-8ef71cc1435b.png)

- 画面に従い、cliのインストールを行う
- インストールが完了したら、

```
$heorku login
```
コマンドを実行し、メールアドレス、パスワードを入力し、ログインします。



## Procfileの作成
- herokuにてアプリを実行するために必要な設定ファイルを準備する
- プロジェクトルート上に以下のように作成する

```
web: bundle exec ruby heroku_study.rb -p $PORT
```
- 今回webアプリケーションなので`web:`と記載する
- 起動コマンド`bundle exec ruby {起動ファイル名}.rb` を定義する
-  最後に、ポートを指定する。$PORTと指定すると、Herokuがポートを自動的に設定する`-p $PORT`

-  プロジェクトをgit管理する
 - もしまだプロジェクトをgit管理していなければ、gitを導入しcommitする
 - プロジェクトのルートにて、 `git init`
 - `git add -A`とりあえず全部addし
 - `git commit -m 'initial commit'`　で一旦git管理はok

## Heroku上にアプリケーションを作成する
- herokuコマンドを実行し、heroku常に、これからアプリを載せるサーバを用意する
- `heroku create`を実行する

```
$ heroku create
Creating app... done, ⬢ calm-{...}
https://calm-{...}.herokuapp.com/
 | https://git.{...}.git
```
- サーバが用意される
 - アプリケーション名:calm-{...}
 - エンドポイント：https://calm-{...}.herokuapp.com/
 - gitリポジトリ（ここにpushするとアプリケーションに反映される）:https://git.{...}.git

## Rakeタスク・マイグレーションの準備
- sqlite3で開発していた場合、sqlite3はheroku対応されていないため、他のDBに変更する必要があります。この時、DDLを流したりなどで、マイグレーションを行う仕組みができている必要があります。   少し長くなりますが、Rakeタスクをアプリに追加し、マイグレーションを行い、heroku上にDBを作成していくプロセスを行います
- database(PostgreSQL)の準備
 - もしまだposgresqlを環境にインストールしていなければ、インストールする
 - `brew install postgresql` (macの場合)

- Gemの追加
 - Gemfileにpgを追加し、Bundle installする
 - まだ入っていなければ、ActiveRecordを追加
 - sinatraでマイグレーションを行うために、sinatra-activerecordを導入する
 - sqlite3はdevelopmentの場合だけに適用することを明示する

```ruby:Gemfile
gem 'pg'
gem 'activerecord'
gem 'sinatra-activerecord'
gem 'sqlite3', groups: %w(test development), require: false
```

- また、環境ごとにDBを分けるため、gemfileを以下のように修正する

```
source 'https://rubygems.org'
gem 'sinatra', :github => 'sinatra/sinatra'
gem 'rake'
gem 'sinatra-contrib'
gem 'activerecord'
gem 'rack_csrf', '~> 2.5'
gem "sinatra-activerecord"
group :development do
  gem 'sqlite3'
end
group :production do
  gem 'pg'
  gem "activerecord-postgresql-adapter"
end
group :test do
  gem 'rspec'
  gem 'rack-test'
end

```

- ローカル上にgemを落とすため、--pathを指定してbundle installする
- bundle exec 

```
bundle install --path=vendor/bundle
```
> GitHub
> https://github.com/janko-m/sinatra-activerecord#setup

- なのですが、あとでデプロイ後に、heroku logsで起動ログを確認したところ、vender/bundleは入れない方が良い、というワーニングが出ていたので、.gitignoreで、vendor以下をリポジトリから除外しました

```:.gitignore
/vendor/
```


### config.ru　を作成
- アプリケーションルートで、以下のファイルを作成し、起動ファイルでrequireする
- まず最初にconfig.ruファイルがherokuから呼び出される。ここからアプリケーションが実行される
 - tipsとして、アプリに問題がある場合、heloku logsで最初にエラーの始まりとして表示されるのは、config.ruが出てくる、そこからネストして具体的なエラーの原因が絞り込まれる、というログの出方をしていた


```ruby:config.ru
require './{起動ファイルの拡張子なし}'
run Sinatra::Application

```

- sinatraの場合、このアプリがsinatraであることを伝えるために必要
- 今回の場合`require './heroku_study'` になる

### Rakefileを作成する
 - プロジェクトのルートに、以下のファイルを作成します
 - これにより、rakeタスク`db:create_migration ` `db:migrate`が追加されます

```ruby:Rakefile
require 'sinatra/activerecord'
require 'sinatra/activerecord/rake'
```

- これで、rakeタスクが利用可能になります。利用可能なタスクは以下です。

```
$ bundle exec rake -T
rake db:create              # Creates the database from DATABASE_URL or config/datab...
rake db:create_migration    # Create a migration (parameters: NAME, VERSION)
rake db:drop                # Drops the database from DATABASE_URL or config/databas...
rake db:environment:set     # Set the environment value for the database
rake db:fixtures:load       # Loads fixtures into the current environment's database
rake db:migrate             # Migrate the database (options: VERSION=x, VERBOSE=fals...
rake db:migrate:status      # Display status of migrations
rake db:rollback            # Rolls the schema back to the previous version (specify...
rake db:schema:cache:clear  # Clears a db/schema_cache.yml file
rake db:schema:cache:dump   # Creates a db/schema_cache.yml file
rake db:schema:dump         # Creates a db/schema.rb file that is portable against a...
rake db:schema:load         # Loads a schema.rb file into the database
rake db:seed                # Loads the seed data from db/seeds.rb
rake db:setup               # Creates the database, loads the schema, and initialize...
rake db:structure:dump      # Dumps the database structure to db/structure.sql
rake db:structure:load      # Recreates the databases from the structure.sql file
rake db:version             # Retrieves the current schema version number
```

### マイグレーション
- マイグレーションファイルを以下で作成します
- `bundle exec rake db:create_migration NAME=create_users`
- マイグレーションファイルが作成されました

```ruby:db/migrate/20180718105504_create_users.rb
class CreateUsers < ActiveRecord::Migration[5.2]
  def change
  end
end

```

- テーブル定義
 - idは自動で準備される
 - nameカラム
 - code（外部キーを想定）
 - 以上の構成のテーブルを作成する

```ruby:db/migrate/20180718105504_create_users.rb
class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t| 
      t.string :name
      t.string :code
    end
  end
end
```


### DB(PostgreSQL)の接続設定
- 起動ファイル(今回はheroku_study.app）に接続設定を追加

```heroku_study.app
ActiveRecord::Base.establish_connection(
  ENV['DATABASE_URL'] )
```

- `DATABASE_URL` この環境変数に、このDBがposgresであること、host、ポート、DB、一色の情報が乗った規定されたスキームの値が乗ってくるので、それを利用してhelok上では動作する

- ***本当は以下のように設定したかった。***
 - `ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'] || 'sqlite3://localhost/herdb.db')`
 - こうして、herokuではpostgres、そうでなければ（ローカルでは）sqlite3にしたかった
 - しかし、deploy後に、画面がアプリケーションエラーとなり、`heroku logs` を確認すると、rack_upでクラッシュ、原因は`database configuration does not specify adapter`となった
 - DBの特定の設定がされていない、という内容だった。
 - 一旦、ローカルでは動かなくなってしまうがpostgresql一つを指定したところ、正常に動作した。この問題も、何らかの方法で解決したい

- Rakeファイルにも設定を追加

```ruby:Rakefile
require 'sinatra/activerecord'
require 'sinatra/activerecord/rake'

ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'] || 'sqlite3://localhost/herdb.db')
```

> このパス指定はなにか
> https://apidock.com/rails/ActiveRecord/Base/establish_connection/class
> SQLite3繋がらない問題
> http://eri-twin.hateblo.jp/entry/2018/02/26/200248

### herokuにpushする
 - その前に、変更を commitするのを忘れずに
 - `git add .` `git commit -m "コメント"`  

```
git push heroku master
```

- postgresqlを利用するためのアドオンをherokuに追加する

```
heroku addons:add heroku-postgresql
```

### heroku上のDBをマイグレートする

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

- これでアプリの準備はできているはずのため、情報を以下で確認する

```
$ heroku apps:info
=== calm-sample
Addons:         heroku-postgresql:hobby-dev
                heroku-postgresql:hobby-dev
Auto Cert Mgmt: false
Dynos:          web: 1
Git URL:        https://git.heroku.com/calm-samplegit
Owner:          ..@sample.com
Region:         us
Repo Size:      12 MB
Slug Size:      15 MB
Stack:          heroku-16
Web URL:        https://calm-sample.herokuapp.com/
```

### うまくいかない場合は、以下のコマンドでログを確認する
- `heroku logs`




# 参考
> 公式
> https://jp.heroku.com/home
> Heroku+Ruby+SinatraでReplyにオウム返しするLineBotを作った
> https://qiita.com/fullmated/items/81d1a49ed3d49eda2285
> ドットインストール
> https://dotinstall.com/lessons/basic_heroku
> Herokuに速攻デプロイするSinatraアプリテンプレートをつくる #1
> http://totutotu.hatenablog.com/entry/2015/06/10/Heroku%E3%81%AB%E9%80%9F%E6%94%BB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8BSinatra%E3%82%A2%E3%83%97%E3%83%AA%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%92%E3%81%A4
> Herokuに速攻デプロイするSinatraアプリテンプレートをつくる #2 PostgreSQL編
> http://totutotu.hatenablog.com/entry/2015/06/10/Heroku%E3%81%AB%E9%80%9F%E6%94%BB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%99%E3%82%8BSinatra%E3%82%A2%E3%83%97%E3%83%AA%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%92%E3%81%A4_1 
> PostgreSQLの導入とマイグレーションを導入する
> HerokuではSQLite3が使えない？！
> https://qiita.com/MosamosaPoodle/items/7149aa66f1c087472777
> MacにPostgreSQLをインストール
> https://qiita.com/_daisuke/items/13996621cf51f835494b
> MacのRailsアプリでPostgreSQLを使う方法
> https://qiita.com/yh2020/items/8be3087004d100fe752b
> Herokuにデプロイできない非エンジニアです。
> https://qiita.com/Taak15/items/8a7325c302d0d1b019f5