はじめに
いろんな方のを参考に課題を進めていますが「?」が発生中。今回はマイグレーションファイル作成のなかでの疑問点になります。
環境
- Windows, WSL
- Docker
- Ruby 3.2.3
- Rails 7.1.3
どういう状況だったのか
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
) が追加されます。 -
生成されるマイグレーションファイルには以下のようなコードが含まれます:
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
モデルと関連付けられます:class Authentication < ApplicationRecord belongs_to :user end
-
2:rails generate model Authentication user:integer provider:string uid:string
-
user:integer
:-
このオプションを使うと、単純に
user_id
という整数型のカラムが生成されます。 -
ただし、
User
モデルとの関連付けは手動で設定する必要があります。また、外部キー制約も自動的には追加されません。 -
生成されるマイグレーションファイルには以下のようなコードが含まれます:
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
が自動的には追加されません。これを追加するには、手動で以下のようにコードを記述する必要があります:class Authentication < ApplicationRecord belongs_to :user end
-
2. マイグレーションファイルのカスタム名
rails generate model
コマンドは、マイグレーションファイルの名前を自動的に TIMESTAMP_create_authentications.rb
のように設定しますが、カスタム名でマイグレーションファイルを作成するには、以下のように手動で対応します。
-
通常のモデル生成コマンドを実行:
rails generate model Authentication user:references provider:string uid:string
-
生成されたマイグレーションファイルをリネーム:
-
db/migrate/
ディレクトリに生成されたマイグレーションファイル(例:202406000000_create_authentications.rb
)を以下のようにリネームします:
mv db/migrate/20240604090805_create_authentications.rb db/migrate/20240604090805_sorcery_external.rb
-
-
マイグレーションファイル内のクラス名も変更:
- マイグレーションファイルのクラス名もリネームに合わせて変更します:
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
を使用する理由や利点としては、以下のようなものが考えられます
-
より柔軟な制御:
-
user:integer
を使用すると、references
のように自動的に外部キー制約や関連付けが追加されないため、開発者がデータベース設計やモデルの関連を自分で完全にコントロールできます。たとえば、外部キー制約が不要な場合や、特定の関連付けを手動で設定したい場合に役立ちます。
-
-
外部キー制約の不要な場合:
- 特定の状況では、外部キー制約を追加しないほうが良い場合があります。たとえば、大量のデータをインポートする際に外部キー制約がパフォーマンスのボトルネックになる場合や、関連モデルがないことが許容される場合です。
-
異なる関連付けを手動で設定する場合:
-
references
を使うとbelongs_to
関係が自動的に設定されますが、プロジェクトの設計上、異なる関連付けが必要な場合に、integer
を使用することで、意図した関連を手動で設定することができます。
-
★マイグレーションファイルの名前変更
-
手動でのリネーム:
- マイグレーションファイルを手動でリネームすることができます。たとえば、
db/migrate/TIMESTAMP_create_authentications.rb
をdb/migrate/202406000000_sorcery_external.rb
のように変更することは問題ありません。
- マイグレーションファイルを手動でリネームすることができます。たとえば、
-
クラス名の変更:
-
ファイル名を変更するだけでなく、そのファイル内のクラス名もリネームに合わせて変更する必要があります。クラス名とファイル名が一致していないと、Rails はそのマイグレーションを認識しません
class SorceryExternal < ActiveRecord::Migration[7.1] # マイグレーション内容 end
-
★モデルファイルの名前変更
-
手動でのリネーム:
- モデルファイル(例:
app/models/authentication.rb
)の名前を変更する場合、対応するクラス名も変更する必要があります。 - 例えば、ファイルを
app/models/auth.rb
に変更する場合、ファイル内のクラス名もclass Auth < ApplicationRecord
のように変更します。
- モデルファイル(例:
-
関連するコードの修正:
- モデル名を変更した場合、そのモデルを参照するすべてのコード(例えば、他のモデルやコントローラー内の関連付け、バリデーション、クエリなど)を更新する必要があります。
まとめ(利点と名前変更について)
-
user:integer
を使用する利点として、より柔軟な制御や外部キー制約を避けたい場合に適しています。 - マイグレーションファイルやモデルファイルを生成した後で名前を変更することは可能ですが、対応するクラス名や参照箇所も変更する必要があります。
さいごに
refrences
を利用することは便利な反面、思わぬエラーが起きる可能性がありinteger
の方が応用がきくのかな。と感じました。
また、名称変更では、ファイル名を変えて終わりではなく、ちゃんと対応するクラス名も変更しないといけないという事も学ぶことができました。
ここだけ変更すれば大丈夫!というわけではないので気を付けたいです💦
今回の記事が何か参考になれば幸いです。