LoginSignup
0

More than 3 years have passed since last update.

【Rails】データのマイグレーションの理解と内容制限

Posted at

マイグレーションの適用を理解する

DBのマイグレーションは、1つのマイグレーションが1つのバージョンとして扱われるので、1つのマイグレーションを適用することでバージョンを1つ上げることができ、適用済みのマイグレーションを1つ取り消すことでバージョンを1つ下げることができます。

rails g migrationコマンドで生成されるファイルのchangeメソッドの処理は、コマンド rails db:migrate でバージョンが上がり、コマンド rails db:rollbackでバージョンが下がります。このchangeメソッド内の処理は自動的に、適切に処理してくれます(例外あり)。

schema.rb

Railsは現在のDBの構造はdb/schema.rbに自動出力されます。マイグレーションの適用や外しで自動的に出力されます。

データ内容の制限

データには想定される「内容の範囲」があり、そぐわない値が格納されないようできるものがあります。
一般的に以下の4つがRailsアプリでよく利用されます。

  • データ型
  • NOT NULL制約
  • 文字列カラムの長さの制限
  • ユニークインデックス

データ型

DBのカラムには型を指定します。主なデータ型は以下の表です。

データ型 説明
:boolean 真偽値
:integer 符号付き整数
:float 浮動少数点数
:string 文字列(短い文字列)
:text 文字列(長い文字列)
:date 日付
:datetime 日時

NOT NULL制約

DBのカラムの値としてNULL(空の値)を格納する必要がない場合は、NOT NULL制約を物理的にNULLを保存できないようにしてくれます。
作成した投稿アプリでは、Postモデルの「投稿内容」(content)につけるのが適当でしょう。
postsテーブルのcontentカラムにNOT NULL制約をつける、つまり既に作ってあるテーブルに制約をつける場合にも、マイグレーションを利用します。

マイグレーションを作るには、まずgeneratorを使って雛形ファイルを生成します。名前は「ChangePostContentNotNull」とします。

bin/rails g migration ChangePostsContentNotNull
Running via Spring preloader in process 10646
      invoke  active_record
      create    db/migrate/XXXXXXXXXXXX_change_posts_content_not_null.rb

雛形を生成したら、ファイルの中身を次のように編集します。

db/migrate/20210210122203_change_posts_content_not_null.rb
class ChangePostsContentNotNull < ActiveRecord::Migration[5.2]
  def change
    change_column_null :posts, :content, false
  end
end

change_column_nullのtrue,falseでNOT NULL制約のつけはずしができます。
編集を終えたたら、マイグレーションを実行して完了です。

文字列カラムの長さ指定

DBのカラム定義で、必要以上に長いデータの保存を防ぐことができます。マイグレーションで文字列カラムに対してlimitオプションを使います。
今回は投稿内容(content)を50文字に制限する処理を書いて、適用しています。

db/migrate/XXXXXXXXXXXX_change_posts_content_limit50.rb
class ChangePostsContentLimit50 < ActiveRecord::Migration[5.2]
  def up
    change_column :posts, :content, :text, limit: 50
  end
  def down
    change_column :posts, :content, :text
  end
end

change_columnでは、バージョンを戻す際の処理を、バージョンを上げる際のコードから自動生成できません。そのため、changeメソッドではなくupメソッドにバージョンを上げる処理、downメソッドにバージョンを下げる処理を書いています。

ユニークインデックス

あるテーブルのあるカラムのデータが、全レコード内で一意である(他と被らない)場合には、ユニークインデックスを作成することで一意性を確保できます。仮にcontentにユニークインデックスを追加したい場合は以下のようなファイルを作ると良いでしょう(実際には行っていません)。

/XXXXXXXXXXXX_add_index_to_posts.rb
class AddIndexToPosts < ActiveRecord::Migration[5.2]
  def change
    add_index :content, unique: true
  end

カラムにユニークインデックスを追加することで、重複した値がDBに存在することが防げます。
なお、NULL同士は常に異なる値だとみなされるので、ユニークインデックスを追加したカラムの値がNULLのレコードは複数存在することができます。

参考

現場で使える Ruby on Rails 5速習実践ガイド

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0