Rails Model migration - izudon/izudon.github.io GitHub Wiki
- マイグレーションの実行(最後まで実行)
$ rails db:migrate
- マイグレーションを1つ戻す
$ rails db:rollback
- マイグレーションをいくつか戻す
$ rails db:rollback STEP=<N>
- マイグレーションがどこまで実行されたかを確認
$ rails db:version
- マイグレーションをあるバージョンまで進ませる。
$ rails db:migrate VERSION=<version>
- マイグレーションを3つ戻し再度3つ実行する
$ rails db:migrate:redo STEP=3
- あ
$ rails db:migrate:status
- マイグレーションファイルは
rails g migrationコマンドで生成できるが、 最終的には手作業目視確認にて完成させなければならない。 - マイグレーションファイル名、クラス名、マイグレーションの内容には、
関連性があり、
ある種の規則をが守られていなければエラーとなってマイグレーションできない。 - 参考資料:
Active Record マイグレーション - Railsガイド
- マイグレーションファイルの作成。
$ rails g migration <マイグレーションクラス名> [[カラム1] [カラム2]...]
- マイグレーションファイルの作成取消。
$ rails d migration <マイグレーションクラス名>
- カラム追加のマイグレーションファイル作成
$ rails g migration AddPriceToSomethings price:integer
-
add_columnを呼び出すchangeメソッドが定義されている。
-
- カラム削除のマイグレーションファイル作成
$ rails g migration RemovePriceFromSomethings price:integer
-
remove_columnを呼び出すchangeメソッドが定義されている。
-
- マイグレーション クラス名 は パスカルケース(PascalCase) 。
- マイグレーション ファイル名 は スネークケース(snake_case) 。
-
テーブル名 や カラム名 は スネークケース(snake_case) 。
- キャメルケース(camelCase)
- パスカルケース(PascalCase)
- スネークケース(snake_case)
- ケバブケース(kebab-case)
- テーブル
- 作成
CreateTttt - 削除
DropTttt
- 作成
- カラム
- 追加
AddCcccToTttt - 削除
RemoveCcccFromTttt
- 追加
title:string content:text user:references
- Rails の認識ではDBは以下のようなオブジェクトからなり、
それぞれaddしたりremoveしたり、changeしたりするものである。
- テーブル系
-
create_drop_rename_change_table -
create_drop_join_table
-
- カラム系
-
add_remove_rename_change_column -
add_remove_reference(他テーブルへの参照(≒外部キー列)) -
add_remove_timestamps(作成日時と更新日時)
-
- 制約系
-
add_remove_rename_index(インデックス(一意性制約も含む)) -
add_remove_foreign_key(外部キー制約) -
add_remove_check_constraint(バリデーション)
-
- 属性系
-
change_column_comment(カラムへのコメント) -
change_column_default(カラムのデフォルト値) -
change_column_null(カラムの非ヌル制約) -
change_table_comment(レーブルへのコメント)
-
- ActiveRecord::ConnectionAdapters::SchemaStatements
- ActiveRecord::ConnectionAdapters::TableDefinition
- ActiveRecord::ConnectionAdapters::Table
create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options)
- 何も指定しなければ
* オートインクリメントされる
* 整数型のカラムが
*idという名称で
* 勝手に 作成される。
create_table :user do |t|
t.string :email
t.timestamps
end-
create_tableのid:オプションに、
カラム名を指定すれば変えられる。
create_table :user, id: :member_no do |t|
t.string :email
t.timestamps
end-
create_tableのid:オプションに、
型を指定すれば変えられる。-
:stringなど、整数型以外を指定した場合には、
オートインクリメントの指定も外れる。 -
:bigintなど、integer以外でも整数型を指定した場合には、
オートインクリメントの指定は継続される。
-
create_table :user, id: :string do |t|
t.string :email
t.timestamps
end-
create_tableのオプションでは対応不可能になってくるので、
id:オプションにはfalseと指定し、
列として明示的に定義しprimary_key: trueオプションをつける。
create_table :user, id: false do |t|
t.string :id, limit: 10, primary_key: true
t.string :email
t.timestamps
end-
create_tableのprimary_keyオプションに、
カラム名を配列で指定する。-
primary_key: trueを複数カラムに指定するとエラーとなる。 - Rails は複合主キーに対応していないという噂があったが、
公式ドキュメント に堂々と乗っているのを先日発見した。
("Composit Primary Key"(複合主キー)の節)
-
- 但し実行時にこんなワーニングが出るので、
「非ヌル制約」+「(複合での)一意性制約」を併せて指定しておくと無難だと思う。WARNING: Active Record does not support composite primary key. authorizations has composite primary key. Composite primary key is ignored.
create_table :user, id: [:office_code, :desk_no] do |t|
t.string :office_code, limit: 10
t.integer :desk_no
t.string :email
t.timestamps
end
add_index :user, [:office_code, :desk_no], unique: trueadd_column(table_name, column_name, type, **options)
カラムを追加する(一般的な列に適した列追加メソッド)。
create_table の t.xxxxx の正体はこれ。
-
t.columnはまさにこれ。 -
t.integerなどは、
t.column type: :integert.column :integerなどの略記。
(第1引数であるから最初に指定するなら引数名を省ける)
-
type:型を指定 -
primary_key:(単列での)主キー指定- 2つ以上のカラム =>
create_tableメソッドのprimary_keyオプションを使う(既述)。
- 2つ以上のカラム =>
-
index:(単列での)インデックス要否- 2つ以上のカラム =>
add_indexメソッドを使う。 -
trueまたはadd_indexメソッドのオプションをそのまま指定する。 -
index: { unique: true }で「(単列での)一意性制約」となる。
- 2つ以上のカラム =>
-
limit:長さの制約(文字列長やバイト長) -
null:非ヌル制約(falseでヌル不可) -
default:デフォルト値の指定
外部キー列を追加する(のに適した列追加メソッド)。
-
create_tableのt.referencesの正体はこれ。
create_table :followers do |t|
t.references :user, foreign_key: true
t.references :follower, foreign_key: true
t.timestamps
endadd_reference(table_name, ref_name, **options)
-
ref_name(第一引数)- 第一引数は「関係名」とでもいうべきラベルである(多分)。
- 参照先テーブルへの明示的な指定がなければこれはテーブル名(単数形)と解される。
-
foreign_key:外部キー制約(+インデックス)をつける。-
trueまたはadd_foreign_keyメソッドのオプションをそのまま指定する。-
to_table:参照先テーブル名を明示的に指定する。 -
column:カラム名を明示的に指定する。 - :
-
-
-
index:インデックス要否(デフォルトはtrue) -
null:ヌル可否 polymorphic:-
type:型
-
type:を指定しないと、勝手に整数型にされ、
参照先のテーブルの主キーが文字列型の場合など、型が一致せず、
妙な不具合が起こることが、少なくとも SQLite3 を使った時起きた。 - 相手型の主キーのそれを
type:limit:には指定すべきと覚えておこう。
-
null: trueと指定しても、値がnilのとき撥ねられることがあった。 - これは、レコード格納以前に、ヴァリデーション で撥ねられていた。
-
belongs_toにoptional:trueを指定することで、
(validatesではなくbelongs_toの話)
外部キーの値がnilでも、ヴァリデーションが通り、格納できるようになる。class Token < ApplicationRecord belongs_to :user, optional: true end
-
to_table:に 参照先テーブル名を指定し、
t.referencesの第一引数は「関係名」と位置付け、
foreign_key:の値を(真偽値ではなく)ハッシュにする。
create_table :followers do |t|
t.references :user, foreign_key: { to_table: :users }
t.references :follower, foreign_key: { to_table: :users }
t.timestamps
endadd_foreign_key(from_table, to_table, **options)
-
to_table:(第一引数) 参照先テーブル名を明示的に指定する。 -
primary_key:to_tableの主キー列名の指定(デフォルトはid)-
to_tableが複合主キーの場合は配列での指定。
-
-
column:from_tableに追加されるカラム名を明示的に指定する。-
to_tableが複合主キーの場合は配列での指定。
-
-
index:インデックス要否(デフォルトはtrue) -
on_delete親レコードの削除時の振る舞い -
on_update親レコードの更新時の振る舞い
-
公式ドキュメント
ではとても素晴らしいことを書いているが、実際問題としては、
テーブル名(単数系)で指定すると動作しないことがあると思う。
カラム名で指定するのがよいかと思う。- エラー:
one: id: 1 user: user_one
- うまくいく:
one: id: 1 user_id: user-one-id
- エラー:
add_index(table_name, column_name, **options)
インデックスを追加する。
インデックスの一種と位置付けられている。
unique: true をつける。
create_table :user, id: [:office_code, :desk_no] do |t|
t.string :office_code, limit: 10
t.integer :desk_no
t.string :email
t.timestamps
end
add_index :user, :email , unique: true
add_index :user, [:office_code, :desk_no], unique: true- 文字列や数値
- 引用符なしでそのまま書いて良い。
- 日付時刻型
- 何分前といった表現が使える(ERB)。
- カラムがヌル
- 値に
null(または~)を指定。
- 値に
- バイナリ値を指定したい
- 値を
!!binary |で始め、次行以降に Base64 形式で書く。
- 値を
user_without_email:
id: s00u9012
name: "User without email"
email: null # または '~'
age: 19
photo: !!binary |
8f8ev6nzZQL9VvpPF9QlkuIlwGn5hj43/mPvAUbo48/zQ+bQ+GHLWLXWk8K+
QW1Ug2Ax/el+6BMV0FjJA3UD2UUvpyaGD6juqIrincwnDYbC2MnLEIeab6R3
:
SLGHBGgh16j74mfEEstpw3g=
updated_at: <%= Time.current.to_s(:db) %>
created_at: <%= 3.days.ago %>