Railsマイグレーションとモデルのアソシエーション
Ruby on Railsでモデルとマイグレーションファイルを作成して、環境に反映させる手順です。
一度本番に乗ってしまうとそうそう作成するものではないので、やり方を忘れた際の備忘録として使えるように書こうと思います。
実行環境
・Rails 7.1.3
・ruby 3.0.2p107
・モデルファイルとマイグレーションファイルを同時に作る
・マイグレーションファイルに必要なメソッドを書く
・マイグレーションを実行する
・モデルファイルにアソシエーション定義を書く
その他、必要な情報があれば補足しながらやっていきます。
モデルファイルとマイグレーションファイルを同時に作る
以下のコマンドでモデルファイルとマイグレーションファイルを一括で作成できます。
基本的にテーブル同士のアソシエーションを持っていることが大半だと思うので、外部キーアリの書き方を記載しておきます。
ちなみに、外部キーが付くのは従属側のテーブルなので、間違って親テーブルに付けないよう注意が必要です。
rails g model モデル名 関連するテーブル名:references [カラム名:型] [オプション]
例)
rails g model Survey title:string description:string
rails g model Question survey:references question_title:string
question_description:string
rails g model Option question:references content:string
changeメソッドを使うか判断する
作られたマイグレーションファイルを開くと、changeメソッドが既に定義されていると思います。
class CreateSurvey < ActiveRecord::Migration[7.1]
def change
create_table :surveys do |t|
t.string :title
t.string :description
t.timestamps
end
end
end
Railsガイドによると、Changeメソッドでサポートされているマイグレーション定義に対してはロールバックができるようです。
上記のcreate_tableはchangeメソッドでサポートされているので、ロールバックしたい場合もchangeメソッドさえ定義されていれば問題ありません。
しかし、それ以外のマイグレーション定義を使用したい場合は、生成されたマイグレーションファイルにupメソッドとdownメソッドを定義してロールバックを可能としておく必要があります。
【余談】モデルファイルのみ、後から作りたい場合
しかし、この時点で既にマイグレーションファイルが存在していて、モデルファイルのみ後から生成したい場合はオプションに「-s(スキップ)」を設定します。
rails g model モデル名 [カラム名:型] -s
※既に存在するファイルのみ、生成をスキップ
【余談その2】マイグレーションファイルを二重で作成した場合
誤ってマイグレーションファイルを二重で作成してしまった場合は、以下のコマンドを打ってマイグレーションの状態を確かめましょう。
rails db:migrate:status
結果がdownとなっていれば、マイグレーションファイルを削除することができます。
マイグレーションを実行する
マイグレーションを実行する事でテーブルに対して変更が行われます。
コマンドは以下です。
rails db:migrate
モデルに対するアソシエーション定義
モデルファイルに対してテーブルのアソシエーションを行っていきます。
class Survey < ApplicationRecord
has_many :questions
accepts_nested_attributes_for :questions
end
class Question < ApplicationRecord
belongs_to :survey
has_many :options
accepts_nested_attributes_for :options
end
class Option < ApplicationRecord
belongs_to :question
end
親子孫のリレーションが張られているテーブルを一括で保存するフォームの作り方
Railsコンソールでアソシエーションの確認をする
アソシエーションが効いているか、Railsコンソールで確認してみます。
# 親レコードを作成
Survey.create(title: "abc", description: "def")
# 子レコードを作成
survey.questions.create(question_title: "child_title", question_description: "child_description")
# 孫レコードを作成
survey.questions[0].options.create(content: "grandchild")
今回は以上となります。
ディスカッション
コメント一覧
まだ、コメントがありません