ridgepole 導入はまりどころ

超高速チーム開発中、なのだが、
- DBスキーマの変更が多発
- migration重なりすぎて、最終形が追えない
- 仕様との突合つらい

ということで、[ridgepole](https://github.com/winebarrel/ridgepole)に移行中です。
GWって、ちょうどよいですよね。
だいぶいい形になりそうです。

実運用までには、まだまだ宿題多数。
その過程でのはまりどころ + 残課題をここで整理して潰しこんでいきます。

導入方法は他のいい感じのページにお任せします
例
- [本家](https://github.com/winebarrel/ridgepole#installation)
- [さらばmigration よろしくridgepole](https://re-engines.com/2017/05/03/370/)


# dotenv 付きの config/database.yml と相性が悪い

本PRJでは、config/database.ymlに[dotenv](https://github.com/bkeepers/dotenv)を使用しています。

で、ridgepoleをconfig/database.ymlを元に実行しようとすると、
だいぶ不親切なエラー
  しかも、エラーが浅いのよね。
　verboseにしてもこれ以上の情報がなひ。

```
$ bundle exec ridgepole --verbose -c config/database.yml -E test --export --split --output db/schemas/Schemafile                                                                   
[ERROR] Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)
        /home/ec2-user/environment/base2/vendor/bundle/ruby/2.4.0/gems/mysql2-0.5.1/lib/mysql2/client.rb:90:in `connect'
```

見た感じは、mysql.sockまわり。
アプリケーションは元気なのに、なぜだーと戦い続けた訳です。
'/var/lib/mysql/mysql.sock' (111)
'/var/lib/mysql/mysql.sock' (2)
'/var/lib/mysql/mysql.sock' (13)

原因は、
「ridgepole読み込みのタイミングでconfig/database.yml (内のerbから.env見ている部分)が展開されない」こと。
特定までだいぶ苦戦しました。
読み込めてないなら、もっと手前でエラーだしてくれると嬉しいなぁ…。
syntaxとかとかで。

## 対応状況: DONE　案3 dotenv即時展開 and/or 案4 自前rake task
### 案1　config/database.ymlに.envを展開
庇を貸して母屋を取られた感 orz
やるならrails5.2らしく、confidential.ymlとかまで使って閉じ込めたいですね。
### 案2　config/database.ymlを使わずに、接続情報を直入力
```
$ bundle exec ridgepole --verbose -c 'ADAPTER://USERNAME:PASSWORD@HOST:PORT/SCHEME' -E development --export --split --output db/schemas/Schemafile
```
いやぁ、ないわ orz
### 案3　コマンド実行時に即時展開
dotenv自体にそれ専用の[コマンドが容易](https://github.com/bkeepers/dotenv#sinatra-or-plain-ol-ruby)されてました。
```$ bundle exec dotenv -f ".env" ridgepole -c config/database.yml -E development --export --split --output db/schemas/Schemafile```

### 案4 rake task内から間接的に
[タスク経由での呼び出し](https://qiita.com/EastResident/items/c53c1e69d677f85a4d72#rake%E3%82%BF%E3%82%B9%E3%82%AF%E5%86%85%E3%81%A7%E3%83%AA%E3%82%B9%E3%82%AF%E3%82%92%E6%8B%85%E4%BF%9D%E3%81%99%E3%82%8B)を作成していたところ、
本件発生せず。
すでに envが読み込まれているから、ですね。


# utf8mb4対応
ここら辺を実施するには、カラム毎のcollation/charsetあたりの管理が必要。
で、[公式ドキュメント](https://github.com/winebarrel/ridgepole)曰く
```
You can use the column collation by passing --enable-mysql-awesome (activerecord-mysql-awesome is required)
```

こちらのgem Rails5系には未対応で、うまくgem installできない
見た感じ、依存関係を修正するだけ、じゃないかと思いつつ。

## 対応状況: DONE Rails5系では対応済みらしい

参照: https://so-wh.at/entry/2017/06/26/233103

### 案1 問題発生するまで放置
採用中（ぉ
というのも、問題が再発した訳ではなく、
以下のschema定義ができているので8割くらいどうにかなってるかな、と楽観的に。
```
create_table "banks", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC", force: :cascade do |t|
```
### 案2 修正pullrequest投げる
### 案3 社内レポジトリにフォークしてうちうちに管理


# デフォルトのmigration回りの機能をつぶす
とりあえず、```db/migration```フォルダは削除しました。
とはいえ…
- 世の各種のgemはmigrationベースで動く
　→　migrationを検知して、各開発者にridgepoleに変換させる
- ```rails g migration```, ```rails db:migrate```まわりのコマンドが健在
　→　コマンドを潰し、警告表示
- development/test環境でのmigration(?)忘れが生じる
　→　何らかのタイミングでチェックして警告
あたりが必要かな。

## 対応案: 検討中(80%くらいDONE with 案4)
### 案1 migrationの実行だけ止める　生成は許可
　→　Pending の警告が出るな。さて、どうしよう。
### 案2 rubocop追加して、ゆるーく警告
### 案3 generate modelまわりから migration生成をstop
templateまわりの設定を、軽くいじります [参照](https://stackoverflow.com/a/26692047/9454794)
config/application.rb

```
config.generators do |g|
  g.orm :active_record, migration: false      
end
```

ちなみに、ここら辺のgenerator回りの設定、肥大化してくるので、
個人的に、config/initialize/generator.rbに切り出しています

```
MyApp::Application.config.generators do |g|
  g.stylesheets false
  g.helper false
  g.decorator false
  g.orm :active_record, migration: false      
end

# Use the responders controller from the responders gem
MyApp::Application.app_generators.scaffold_controller :responders_controller
```

### 案4 Migrationのチェック機構を潰す (rack除去)

Migrationがあろうがなかろうが、サービス起動します。

config/application.rb

```
config.middleware.delete ActiveRecord::Migration::CheckPending
```


# 自動デプロイ
capistranoまわりのデプロイについては、いろいろドキュメントがありますね。
[ここ](https://re-engines.com/2017/05/03/370/#capistrano3deployRidgepole)とか[ここ](https://qiita.com/paranishian/items/ff9d4736593c7d5f0295#capistrano%E3%81%A7%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E6%99%82%E3%81%AB%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)とか

capistranoではなく、AWS ElasticBeanstalkを使ってます。
[ebextensions](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/ebextensions.html)まわりで管理する感じになりますね。

## 対応案
### プロジェクトのテンプレート修正
RoRプロジェクトということで、自動でmigrationが組み込まれてるみたいですね。
そこを差し替える形になるのかな。

# コマンドの引数多い
覚えられませんね。しかも、大方デフォルト設定でよいですし。
デフォルト設定用のファイルというのも見当たらない。
皆さんどうしてらっしゃるんだろう？

## 対応案：DONE 案1 必要分だけタスク作成
### 案1 rails db:xxxxx というrake taskを自作して一律導入。
[ここ](https://qiita.com/EastResident/items/c53c1e69d677f85a4d72#rake%E3%82%BF%E3%82%B9%E3%82%AF%E5%86%85%E3%81%A7%E3%83%AA%E3%82%B9%E3%82%AF%E3%82%92%E6%8B%85%E4%BF%9D%E3%81%99%E3%82%8B)を参考にさせていただきました。
とりあえず、apply と exportだけ作ったった
```呼び出し方
$ rails db:export
$ rails db:apply RAILS_ENV=production
```

```
namespace :db do
  config_file = 'config/database.yml'
  schema_file = 'db/schemas/Schemafile'
  
  desc 'apply Schemafile and update schema.rb'
  task apply: :environment do
    ENV['ALLOW_DROP_TABLE'] ||= '0'
    ENV['ALLOW_REMOVE_COLUMN'] ||= '0'
    ENV['RAILS_ENV'] ||= 'development'
    task_return = `ridgepole -E #{ENV['RAILS_ENV']} --diff #{config_file} #{schema_file}`
    column_condition = task_return.include?('remove_column') && ENV['ALLOW_REMOVE_COLUMN'] == '0'
    table_condition = task_return.include?('drop_table') && ENV['ALLOW_DROP_TABLE'] == '0'
    if column_condition || table_condition
      puts '[Warning]this task contains some risks: "remove_column" or "drop_table"'
    else
      sh "ridgepole -E #{ENV['RAILS_ENV']} -c #{config_file} --apply -f #{schema_file}"
      sh 'rake db:schema:dump'
    end
  end

  desc 'write Schemafile from db'
  task :export do
    ENV['RAILS_ENV'] ||= 'development'
    sh "ridgepole -E #{ENV['RAILS_ENV']} -c #{config_file} --export --split --output #{schema_file}"
    sh 'rake db:schema:dump'
  end
end
```

### 案2 いい感じのalias作って、各自に導入さす
alias を .bash_profileあたりに突っ込む感じ。
徹底できないのが、つらみ。
変に環境依存問題で時間とられそうだなー、というわけで、こちらは棄却。

# 参考
https://qiita.com/aosho235/items/1dcc9d23b6680be05579