【豆知識】マイグレーションファイル生成時userはinteger?references?＆名称変更注意点など

# はじめに
いろんな方のを参考に課題を進めていますが「？」が発生中。今回はマイグレーションファイル作成のなかでの疑問点になります。

## 環境
- Windows, WSL
- Docker
- Ruby 3.2.3
- Rails 7.1.3


## どういう状況だったのか
```java
rails generate model Authentication user:references provider:string uid:string

rails generate model Authentication user:integer provider:string uid:string
```
認証機能に関する機能に`gem sorcery`がありますが、Googleやlineも利用したログイン機能などを実装したい時はこちらの`Authentication`というものが関係してくるそうです。（これだけあってもGoogleーなどの認証機能は可能とはならないそうですが、それはまた別記事でまとめてみたいと思います。）

いろんな方のを参考にファイルを見ていくと、単純にGPTなどからえた内容を行うだけでは同じようなファイル名やコードにならないことから、最終的に上記2つのコードが考えられましたが、次のような「？」もありました。

- この二つのコードの違いは？
- それぞれどのようなファイルが生成されるのか？
- GPTからえた内容で行うとマイグレーションファイルの名前が`db/migrate/TIMESTAMP_create_authentications.rb`となるが`202400000_sorcery_external.rb`というようなファイル名への変更はどうすればいいのか？


## 1. 二つの `rails generate model` コマンドの違い

**1：`rails generate model Authentication user:references provider:string uid:string`**

- **`user:references`**:
    - このオプションを使うと、自動的に `user_id` カラムが生成され、`User` モデルとの関連付けが設定されます。
    - 同時に、`user_id` カラムに対して外部キー制約 (`foreign_key: true`) が追加されます。
    - 生成されるマイグレーションファイルには以下のようなコードが含まれます：
        
        ```ruby
        class CreateAuthentications < ActiveRecord::Migration[7.1]
          def change
            create_table :authentications do |t|
              t.references :user, null: false, foreign_key: true
              t.string :provider
              t.string :uid
        
              t.timestamps
            end
          end
        end
        ```
        
- **生成されるモデルファイル**:
    - `app/models/authentication.rb` ファイルには、`belongs_to :user` が自動的に追加され、`Authentication` モデルが `User` モデルと関連付けられます：
        
        ```ruby
        class Authentication < ApplicationRecord
          belongs_to :user
        end
        ```
        
<br>

 **2：`rails generate model Authentication user:integer provider:string uid:string`**

- **`user:integer`**:
    - このオプションを使うと、単純に `user_id` という整数型のカラムが生成されます。
    - ただし、`User` モデルとの関連付けは手動で設定する必要があります。また、外部キー制約も自動的には追加されません。
    - 生成されるマイグレーションファイルには以下のようなコードが含まれます：
        
        ```ruby
        class CreateAuthentications < ActiveRecord::Migration[7.1]
          def change
            create_table :authentications do |t|
              t.integer :user, null: false
              t.string :provider
              t.string :uid
        
              t.timestamps
            end
          end
        end
        ```
        
- **生成されるモデルファイル**:
    - `app/models/authentication.rb` ファイルには、`belongs_to :user` が自動的には追加されません。これを追加するには、手動で以下のようにコードを記述する必要があります：
        
        ```ruby
        class Authentication < ApplicationRecord
          belongs_to :user
        end
        ```
        

## 2. マイグレーションファイルのカスタム名

`rails generate model` コマンドは、マイグレーションファイルの名前を自動的に `TIMESTAMP_create_authentications.rb` のように設定しますが、カスタム名でマイグレーションファイルを作成するには、以下のように手動で対応します。

1. **通常のモデル生成コマンドを実行**:
    
    ```bash
    rails generate model Authentication user:references provider:string uid:string
    ```
    
2. **生成されたマイグレーションファイルをリネーム**:
    - `db/migrate/` ディレクトリに生成されたマイグレーションファイル（例: `202406000000_create_authentications.rb`）を以下のようにリネームします：
    
    ```bash
    mv db/migrate/20240604090805_create_authentications.rb db/migrate/20240604090805_sorcery_external.rb
    ```
    
3. **マイグレーションファイル内のクラス名も変更**:
    - マイグレーションファイルのクラス名もリネームに合わせて変更します：
    
    ```ruby
    class SorceryExternal < ActiveRecord::Migration[7.1]
      def change
        create_table :authentications do |t|
          t.references :user, null: false, foreign_key: true
          t.string :provider
          t.string :uid
    
          t.timestamps null: false
        end
      end
    end
    ```
    

### ここまでのまとめ

- **`user:references` と `user:integer` の違い**: `references` は自動的に外部キー制約とモデル間の関連を追加しますが、`integer` は単純に整数カラムを追加します
- **マイグレーションファイルのカスタム名**: 通常の生成コマンドで作成し、手動でファイル名とクラス名を変更することでカスタム名を使用できます



##  ★`user:integer` を使用する利点

`user:integer` を使用する理由や利点としては、以下のようなものが考えられます

1. **より柔軟な制御**:
    - `user:integer` を使用すると、`references` のように自動的に外部キー制約や関連付けが追加されないため、開発者がデータベース設計やモデルの関連を自分で完全にコントロールできます。たとえば、外部キー制約が不要な場合や、特定の関連付けを手動で設定したい場合に役立ちます。
2. **外部キー制約の不要な場合**:
    - 特定の状況では、外部キー制約を追加しないほうが良い場合があります。たとえば、大量のデータをインポートする際に外部キー制約がパフォーマンスのボトルネックになる場合や、関連モデルがないことが許容される場合です。
3. **異なる関連付けを手動で設定する場合**:
    - `references` を使うと `belongs_to` 関係が自動的に設定されますが、プロジェクトの設計上、異なる関連付けが必要な場合に、`integer` を使用することで、意図した関連を手動で設定することができます。


## **★マイグレーションファイルの名前変更**

- **手動でのリネーム**:
    - マイグレーションファイルを手動でリネームすることができます。たとえば、`db/migrate/TIMESTAMP_create_authentications.rb` を `db/migrate/202406000000_sorcery_external.rb` のように変更することは問題ありません。
- **クラス名の変更**:
    - ファイル名を変更するだけでなく、そのファイル内のクラス名もリネームに合わせて変更する必要があります。**クラス名とファイル名が一致していないと、Rails はそのマイグレーションを認識しません**
        
        ```ruby
        class SorceryExternal < ActiveRecord::Migration[7.1]
          # マイグレーション内容
        end
        ```
        

## ★**モデルファイルの名前変更**

- **手動でのリネーム**:
    - モデルファイル（例: `app/models/authentication.rb`）の名前を変更する場合、対応するクラス名も変更する必要があります。
    - 例えば、ファイルを `app/models/auth.rb` に変更する場合、ファイル内のクラス名も `class Auth < ApplicationRecord` のように変更します。
- **関連するコードの修正**:
    - モデル名を変更した場合、そのモデルを参照するすべてのコード（例えば、他のモデルやコントローラー内の関連付け、バリデーション、クエリなど）を更新する必要があります。

## まとめ（利点と名前変更について）

- `user:integer` を使用する利点として、より柔軟な制御や外部キー制約を避けたい場合に適しています。
- マイグレーションファイルやモデルファイルを生成した後で名前を変更することは可能ですが、対応するクラス名や参照箇所も変更する必要があります。


## さいごに
`refrences`を利用することは便利な反面、思わぬエラーが起きる可能性があり`integer`の方が応用がきくのかな。と感じました。
また、名称変更では、ファイル名を変えて終わりではなく、ちゃんと対応するクラス名も変更しないといけないという事も学ぶことができました。
ここだけ変更すれば大丈夫！というわけではないので気を付けたいです💦
今回の記事が何か参考になれば幸いです。