マイグレーションでできることのまとめ
マイグレーションとは
SQLを直接使わずに、データベースのテーブルやカラムを変更できる仕組み。 変更の1つ1つをRubyのファイル(マイグレーションファイル)として実現している。
マイグレーション作成コマンド
$ rails generate migration クラス名
クラス名は何でもOKだが、基本は「すること+テーブル名」。 例えばUserテーブルのhogeカラムを変更したい場合は ChangeHogeToUser で、Userテーブルを削除したい場合は DropUser となる。
マイグレーションでできること
マイグレーションを可逆的にする(up, down)
upはマイグレーション実行時に実行され、downはロールバック実行時に実行されるメソッド。 下記のコードでは、マイグレーションを実行するとテーブルが削除され、ロールバックを実行すると元のテーブルが復元される。
class DropUser < ActiveRecord::Migration[5.0] # 変更内容 def up drop_table :users end # 変更前の状態 def down create_table :users do |t| t.string :uuid t.string :name t.timestamps end end end
テーブル名の変更
下記のコードではテーブル名をissuesからtasksに変更している。
class RenameIssueToTask < ActiveRecord::Migration def change rename_table :issues, :tasks end end
既存カラムの変更
下記のコードではUserモデルのuuidカラムをNOT NULL制約に変更している。
class ChangeColumnToUser< ActiveRecord::Migration def up change_column :users, :uuid, :string, null: false, default: 0 end def down change_column :users, :uuid, :string, null: true, default: 0 end end
既存カラムを変更する際のオプション
①NULL / NOT NULL
# NULL change_column :テーブル名, :カラム名, :型, null: true # NOT NULL change_column :テーブル名, :カラム名, :型, null: false
②インデックス
特定のカラムからデータを取得する際に、そのカラムのデータを複製して検索を行いやすくするためのもの。例えばUsersテーブルのnameカラムにインデックスを張ることで、アルファベット順にnameを並べ替えて検索しやすくしてくれる(並び替えた後にどういった検索処理が行われるのかはよく分かってない)
change_column :テーブル名, :カラム名, :型, index: true
③デフォルト値
change_column :テーブル名, :カラム名, :型, default: "piyo"
④長さ
change_column :テーブル名, :カラム名, :string, limit: 12
⑤小数部の精度を指定する
change_column :テーブル名, :カラム名, :型, precision: 6
カラム名の変更
class RenameAgeToNenrei < ActiveRecord::Migration def change rename_column :User, :age, :nenrei end end
カラムを追加/削除する
class AddColumnToUser < ActiveRecord::Migration def change # 追加 add_column :users, :piyo, :string # 削除 remove_column :users, :piyo, :string # まとめて削除 remove_columns :users, :column_1, :column_2 [, ...] # 追加する場所を指定する場合 add_column :users, :piyo, :string, :after => :uuid end end
インデックスを追加/削除する
複合ユニークの使い所は、例えばユーザAから投稿Aへのいいねなど。この組み合わせは一意にしておかないと、この例で言うと同じユーザが1つの投稿に何度もいいねできることになる。
class AddIndexToUser < ActiveRecord::Migration def change # 追加 add_index :users, :name # ユニーク追加 add_index :users, :name, :unique => true # 削除 remove_index :users, :name # 複合インデックスの場合 add_index :users, [:name, :name2] # 複合ユニークの場合 add_index :user_accounts, [:provider, :uid], :unique => true end end
外部キーを作成/削除する
外部キーとは、テーブル同士の紐づけに用いるカラムのこと。usersテーブルとpostsテーブルがあったとして、このpostはどのuserが投稿したものなんだろう?というのをpostsテーブルで確認したい時に、user_idのカラムを用いる。user_idはusersテーブルでは主キーと呼ばれる。
class CreateUserAccounts < ActiveRecord::Migration[5.0] def change create_table :user_accounts do |t| t.references :user, index: true, foreign_key: true t.timestamps end end end
モデル作成時に作成する場合 $ rails g model UserAccount user:references
class AddRefUser < ActiveRecord::Migration def change add_reference :users, :article, foreign_key: true # 外部キーの削除はこちら remove_foreign_key :users, column: :article_id # カラムも一緒に削除する場合はこちら remove_reference :users, :article, foreign_key: true end end
既存のテーブルに追加する場合 $ rails g migration AddArticleToUsers article:references
ポリモーフィックを作る
ポリモーフィックとは、複数の異なる型やオブジェクトに対して共通のインタフェース(Rubyの世界でならメソッドと言い換えてもよさそう)を提供すること。すごく単純化して言うと、同じ名前のメソッドがそれぞれ異なるクラスで規定されていること。もちろんそのメソッドの内容はそれぞれ異なる。ダックタイピングの一種。
class CreateMessages < ActiveRecord::Migration[5.0] def change create_table :messages do |t| t.references :messagable, polymorphic: true t.text :message t.timestamps end end end
モデル作成時に作成する場合:$ rails g model message messagable:references{polymorphic} message:text
実際にポリモーフィックを利用したコードは例えば以下のような感じ。 EmployerとEmployee、どちらもsender_nameという同じ名前のメソッドを所有しているが、 どちらのsender_nameを使う際もコードはMessage.find(params[:id]).messageable.sender_nameとなる。
class Message < ApplicationRecord belongs_to :messageable, polymorphic: true end class Employer < ApplicationRecord has_many :messages, as: :messageable # 共通のインターフェース def sender_name company_name end end class Employee < ApplicationRecord has_many :messages, as: :messageable # 共通のインターフェース def sender_name "#{last_name} #{first_name}" end end