ridgepole動作まとめ

1. [DBがないとエラー](##DBがないとエラー)
2. [空のDBでexportしても何も起きない](##空のDBでexportしても何も起きない)
3. [apply](apply)
4. [変更がない場合はNochange](##変更がない場合はNochange)
5. [差分がない時は何も起きない](##差分がない時は何も起きない)
6. [カラム削除](##カラム削除)
7. [カラム追加](##カラム追加)
8. [ただ単に`.schema`を削除した場合は`Schemafile`の`require`でエラーになる](##ただ単に`.schema`を削除した場合は`Schemafile`の`require`でエラーになる)
9. [ファイル削除した場合でもDROPされずに`Nochange`になる](##ファイル削除した場合でもDROPされずに`Nochange`になる)
10. [DROPの場合`.schema`が残っていても`Schemafile`の`require`を削除しただけでDROPされる](DROPの場合`.schema`が残っていても`Schemafile`の`require`を削除しただけでDROPされる)
11. [データが入っている状態で、apply（カラム追加）してもデータは残る](##データが入っている状態で、apply（カラム追加）してもデータは残る)
12. [データが入っている状態で、apply（カラム名変更）すると空になる](##データが入っている状態で、apply（カラム名変更）すると空になる)
13. [データが入っている状態で、既存のカラムが空の状態で`null:false`に変更するとエラーになる](##データが入っている状態で、既存のカラムが空の状態で`null:false`に変更するとエラーになる)
14. [データが入っている状態で、`null:false`で新規カラム追加しようとするとエラーになる](##データが入っている状態で、`null:false`で新規カラム追加しようとするとエラーになる)
15. [データがある状態で`null:false`のカラム追加でも`default`があれば可能](##データがある状態で`null:false`のカラム追加でも`default`があれば可能)

その他
1. [dotenvなどの導入時要注意](###dotenvなどの導入時要注意)
2. [ER図の自動生成](###ER図の自動生成)
3. [migrationファイルの復活方法はない](###migrationファイルの復活方法はない)
4. [modelをgenerateする時は、`--skip-migration`を付けるのを忘れずに](###modelをgenerateする時は、`--skip-migration`を付けるのを忘れずに)
5. [導入例](###導入例)

## DBがないとエラー
```
# bundle exec rake ridgepole:export
[ERROR] We could not find your database: vwc_dev. Which can be found in the database configuration file located at config/database.yml.

To resolve this issue:

- Did you create the database for this app, or delete it? You may need to create your database.
- Has the database name changed? Check your database.yml config has the correct database name.

To create your database, run:

        bin/rails db:create

        /usr/local/bundle/gems/activerecord-7.0.3/lib/active_record/connection_adapters/postgresql_adapter.rb:81:in `rescue in new_client'
```

## 空のDBでexportしても何も起きない
```
# bin/rails db:create
Created database 'vwc_dev'
Database 'vwc_test' already exists
#
#
# bundle exec rake ridgepole:export
# Export Schema
#
```

## apply
```
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
-- create_table("fund_details")
   -> 0.1828s
-- create_table("fund_financial_tradings")
   -> 0.0643s
-- create_table("fund_headlines")
   -> 0.0634s
-- create_table("fund_real_estate_specifieds")
   -> 0.0705s
-- create_table("product_categories")
   -> 0.0738s
-- create_table("products")
   -> 0.0421s
-- create_table("tenant_booths")
   -> 0.1862s
-- create_table("tenants")
   -> 0.0693s
```

## 変更がない場合はNochange
```
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
No change
```

## 差分がない時は何も起きない
exportされてるっぽいけど、差分がないので何も起きない
1ファイル削除してから実行しても表示は同じだが、削除したファイルが復活する
```
# bundle exec rake ridgepole:export
Export Schema
  write `db/schemas/fund_details.schema`
  write `db/schemas/fund_financial_tradings.schema`
  write `db/schemas/fund_headlines.schema`
  write `db/schemas/fund_real_estate_specifieds.schema`
  write `db/schemas/product_categories.schema`
  write `db/schemas/products.schema`
  write `db/schemas/tenant_booths.schema`
  write `db/schemas/tenants.schema`
  write `db/schemas/Schemafile`
```

## カラム削除
`fund_details.schema`の`t.string "display_link"`を削除してから実行
```
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
-- remove_column("fund_details", "display_link")
   -> 0.0335s
```

## カラム追加
`fund_details.schema`に`t.string "add_column"`を追加してから実行
```
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
[WARNING] PostgreSQL doesn't support adding a new column except for the last position. fund_details.add_column will be added to the last.
-- add_column("fund_details", "add_column", :string)
   -> 0.0029s
```

## ただ単に`.schema`を削除した場合は`Schemafile`の`require`でエラーになる
`fund_details.schema`を削除してから実行
```
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
bundler: failed to load command: ridgepole (/usr/local/bundle/bin/ridgepole)
/usr/local/bundle/gems/ridgepole-1.1.0/lib/ridgepole/dsl_parser/context.rb:102:in `require': cannot load such file -- fund_details.schema (LoadError)
```

## ファイル削除した場合でもDROPされずに`Nochange`になる
`Schemafile`の`require 'fund_details.schema'`を削除してから実行
明示的に`--drop-table`しないとDROPされない
```
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
No change
```

## DROPの場合`.schema`が残っていても`Schemafile`の`require`を削除しただけでDROPされる
`Schemafile`の`require 'fund_details.schema'`を削除してから実行
```
# bundle exec rake ridgepole:drop
Apply `db/schemas/Schemafile`
-- drop_table("fund_details")
   -> 0.0732s
```

## データが入っている状態で、apply（カラム追加）してもデータは残る
`tenants.schema`に`t.string "add_column"`を追加してから実行
```
# rails db:seed
rails aborted!
ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "tenants_pkey"
DETAIL:  Key (id)=(9999) already exists.
/work/db/seeds.rb:1:in `block in <main>'
/work/db/seeds.rb:1:in `each'
/work/db/seeds.rb:1:in `<main>'

Caused by:
PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "tenants_pkey"
DETAIL:  Key (id)=(9999) already exists.
/work/db/seeds.rb:1:in `block in <main>'
/work/db/seeds.rb:1:in `each'
/work/db/seeds.rb:1:in `<main>'
Tasks: TOP => db:seed
(See full trace by running task with --trace)
#
#
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
[WARNING] PostgreSQL doesn't support adding a new column except for the last position. tenants.add_column will be added to the last.
-- add_column("tenants", "add_column", :string)
   -> 0.0101s
```

カラム追加前
```
vwc_dev=# select * from tenants;
  id  | tenant_name |         tenant_log_image          |         created_at         |         updated_at
------+-------------+-----------------------------------+----------------------------+----------------------------
 9999 | test tenant | financial_street/lobby_sample.png | 2022-07-13 15:47:43.044591 | 2022-07-13 15:47:43.044591
(1 row)
```

カラム追加後
```
vwc_dev=# select * from tenants;
  id  | tenant_name |         tenant_log_image          |         created_at         |         updated_at         | add_column
------+-------------+-----------------------------------+----------------------------+----------------------------+------------
 9999 | test tenant | financial_street/lobby_sample.png | 2022-07-13 15:47:43.044591 | 2022-07-13 15:47:43.044591 |
(1 row)

```

## データが入っている状態で、apply（カラム名変更）すると空になる
`tenants.schema`の`t.string "tenant_name"`を`t.string "tenant_name_cange_name"`に変更してから実行

remove_column & add_columnになる
```
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
[WARNING] PostgreSQL doesn't support adding a new column except for the last position. tenants.tenant_name_cange_name will be added to the last.
-- add_column("tenants", "tenant_name_cange_name", :string)
   -> 0.0080s
-- remove_column("tenants", "tenant_name")
   -> 0.0081s
```

変更後
```
vwc_dev=# select * from tenants;
  id  |         tenant_log_image          |         created_at         |         updated_at         | add_column | tenant_name_cange_name
------+-----------------------------------+----------------------------+----------------------------+------------+------------------------
 9999 | financial_street/lobby_sample.png | 2022-07-13 15:47:43.044591 | 2022-07-13 15:47:43.044591 |            |
(1 row)
```

## データが入っている状態で、既存のカラムが空の状態で`null:false`に変更するとエラーになる
`tenants.schema`の`t.string "add_column"`を`t.string "add_column", null: false`に変更してから実行
```
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
-- change_column("tenants", "add_column", :string, {:null=>false, :default=>nil})
[ERROR] PG::NotNullViolation: ERROR:  column "add_column" of relation "tenants" contains null values

* 1: change_column("tenants", "add_column", :string, **{:null=>false, :default=>nil})
        /usr/local/bundle/gems/activerecord-7.0.3/lib/active_record/connection_adapters/postgresql/database_statements.rb:48:in `exec'
```

## データが入っている状態で、`null:false`で新規カラム追加しようとするとエラーになる
`tenants.schema`に`t.string "not_null_column", null: false`を追加してから実行
```
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
[WARNING] PostgreSQL doesn't support adding a new column except for the last position. tenants.not_null_column will be added to the last.
-- add_column("tenants", "not_null_column", :string, {:null=>false})
[ERROR] PG::NotNullViolation: ERROR:  column "not_null_column" of relation "tenants" contains null values

* 1: add_column("tenants", "not_null_column", :string, **{:null=>false})
        /usr/local/bundle/gems/activerecord-7.0.3/lib/active_record/connection_adapters/postgresql/database_statements.rb:48:in `exec'
```

## データがある状態で`null:false`のカラム追加でも`default`があれば可能
`tenants.schema`に`t.string "not_null_column", null: false, default: 'hello'`を追加してから実行
```
# bundle exec rake ridgepole:apply
Apply `db/schemas/Schemafile`
[WARNING] PostgreSQL doesn't support adding a new column except for the last position. tenants.not_null_column will be added to the last.
-- add_column("tenants", "not_null_column", :string, {:null=>false, :default=>"hello"})
   -> 0.0193s
```





##　その他
### dotenvなどの導入時要注意
CF. [dotenv 付きの config/database.yml と相性が悪い](https://qiita.com/ToqTock/items/c185a38fd4e2011ddd64#dotenv-%E4%BB%98%E3%81%8D%E3%81%AE-configdatabaseyml-%E3%81%A8%E7%9B%B8%E6%80%A7%E3%81%8C%E6%82%AA%E3%81%84)


### ER図の自動生成
#### [voormedia/rails-erd](https://github.com/voormedia/rails-erd)

※ migrationファイルがなくても動作を確認

actionsに追加したい
```
      - name: Generete ER図
        run: bundle exec erd --filetype=png --title=${{ github.sha }}

      - name: push to tech-doc
         run: push
```
DBが共有だからER図も一つで良い気もするが、modelの情報(has_manyとか)も必要だから別々？

そもそも(今更)だが、`foreign_key`指定しなくても問題ないのでしょうか？ <= ちゃんと指定してDBに反映してあればER図も簡単説

(er図)[https://github.com/VirtualWallC/tech_doc/blob/develop/vwc_tenant/ER%E5%9B%B3/%E5%8E%9F%E6%9C%AC/%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%20ER%20%E5%9B%B3.jpeg]と実際のDBが一致していないので、やはりER図は手動作成でない方が良いかと思われる。
ex) `tenant_log_image`

#### schemaspy
```
docker run -v "$PWD/db/schema:/output" --net="host" schemaspy/schemaspy:6.1.0 -t pgsql -host localhost:5432 -db vwc_dev -u postgres -p pass
```

### migrationファイルの復活方法はない
#### 1. 手動でmigrationファイルを復活させて`db:migrate`
手動でmigrationファイルを復活させてから実行
```
pg_dump -U postgres -p 5432 --data-only vwc_dev > vwc_dev.dmp
rails db:migrate:reset
psql -U postgres -p 5432 vwc_dev < vwc_dev.dmp
```

#### 2. `db:bump`で`db/schema.rb`で運用する
`rails db:reset`は`db/schema.rb`を元にDB作成します。`db/migrate/**.rb`は使われません。

```
pg_dump -U postgres -p 5432 --data-only vwc_dev > vwc_dev.dmp
rails db:bump
rails db:reset
psql -U postgres -p 5432 vwc_dev < vwc_dev.dmp
```

CF. [24.1. SQLによるダンプ](https://www.postgresql.jp/docs/9.4/backup-dump.html)
[migrationファイル削除コミット](https://github.com/VirtualWallC/vwc/pull/224/commits/bb8785d50006a647a85b047d152afb1aad1b7fcb)


### modelをgenerateする時は、`--skip-migration`を付けるのを忘れずに
ex)
```
rails g model Foo --skip-migration
```

### 導入例
[クックパッドにおける最近のActiveRecord運用事情](https://techlife.cookpad.com/entry/2014/08/28/194147)
[すでに動いているシステムでridgepoleを使うためのメモ](https://qiita.com/nasum/items/d19af5a5937254ba3a97)