LoginSignup
0
2

More than 5 years have passed since last update.

マイグレーションについて

Last updated at Posted at 2019-02-24

はじめに

先週からエンジニアとして働き始めました。

といってもずっとgitの使い方でつまづいていて何もしてないんですが....

マイグレーションに関して少し指摘を受けて忘れないように忘備録として残します。

自分は結構おっちょこちょいなのでうっかり大切なデータ消しちゃったとかやりそうなのでマイグレーションとかは特に気を付けなければ…

何か間違っている点やアドバイスなどがあればコメントしていただけるととても助かります。

マイグレーションファイルの作り方

マイグレーションファイルを作成するときはあんま何も考えず

とりあえず変更出来てればよいか…

位の考えだったのですが実際はそんなことはなく

rails db:migrate
rails db:rollback

が問題なく実行できることを確認する必要があるようです。

理由に関してはあんまりうまく理解できなかったのですが....

マイグレーションの流れ

マイグレーションの流れとしては

まず

rails db:migrate:status

で今の状況を確認します

そうするとこんな感じに履歴が見れます

database: tt_db

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190224051828  Create users
   up     20190224052935  Add address to users
   up     20190224053300  Change address column
   up     20190224054338  Add birthday not null
   up     20190224055456  Add good to users

このupというのはmigrationされた状態ということ

今では5個のマイグレーションファイルがありすべてマイグレーションが実行されている状態であることが分かります。

そしてそれを確認したら次に

rails db

でデータベースにアクセスします。

そして

select * from schema_migrations;

を実行します

そうすると

tt_db=> select * from schema_migrations;
    version
----------------
 20190224051828
 20190224052935
 20190224053300
 20190224054338
 20190224055456
(5 rows)

こういった感じでマイグレーションファイル情報が出てきます。

これはrails db:migrate:statusで出てきたupの情報と一致しているはずです。

次に現在のテーブル定義を確認しておきます

tt_db=> \d users;
                                           Table "public.users"
     Column      |            Type             | Collation | Nullable |              Default
-----------------+-----------------------------+-----------+----------+-----------------------------------
 id              | bigint                      |           | not null | nextval('users_id_seq'::regclass)
 name            | character varying           |           |          |
 email           | character varying           |           |          |
 password        | character varying           |           |          |
 created_at      | timestamp without time zone |           | not null |
 updated_at      | timestamp without time zone |           | not null |
 address         | text                        |           |          |
 birthday        | date                        |           |          |
 password_digest | character varying           |           |          |
 good            | character varying           |           |          |
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)

こんなかんじでpostgresqlの場合は\d テーブル名でテーブルの情報が確認できます。

そして次に\qでデータベースから離脱してマイグレーションファイルを作成していきます。

今回はheightという身長を保存するカラムを作成していきます。

その場合は

rails g migration add_height_to_users

これを実行

そうするとdb/migrate以下にマイグレーションファイルがこんな感じで作成されているはずです。

class AddHeightToUsers < ActiveRecord::Migration[5.2]
  def change
  end
end

ここに変更する内容を書いていきますがrails db:migrate rails db:rollbackを確実に実行できるようにしていくために

class AddHeightToUsers < ActiveRecord::Migration[5.2]
  def up
   add_column :users, :height, :string
  end

  def down
     remove_column :users, :height
  end 
end

みたいにmigrateされるときとrollbackされるときの処理を別々に書いていきます。

rails db:migrateを実行する前に現在のマイグレーションファイルの状態をrails db:migrate:statusで確認します

そうすると

database: tt_db

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190224051828  Create users
   up     20190224052935  Add address to users
   up     20190224053300  Change address column
   up     20190224054338  Add birthday not null
   up     20190224055456  Add good to users
  down    20190224063318  Add height to users

こんな感じになっているはずです。

この最後のdownがいま作ったマイグレーションファイルです。

これを確認したらrails db:migrateを実行します

成功するのでrails dbでデータベースにアクセスして問題なく変わっているか確認します。

tt_db=> \d users;
                                           Table "public.users"
     Column      |            Type             | Collation | Nullable |              Default
-----------------+-----------------------------+-----------+----------+-----------------------------------
 id              | bigint                      |           | not null | nextval('users_id_seq'::regclass)
 name            | character varying           |           |          |
 email           | character varying           |           |          |
 password        | character varying           |           |          |
 created_at      | timestamp without time zone |           | not null |
 updated_at      | timestamp without time zone |           | not null |
 address         | text                        |           |          |
 birthday        | date                        |           |          |
 password_digest | character varying           |           |          |
 good            | character varying           |           |          |
 height          | character varying           |           |          |
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)

こんな感じで最後にheightカラムが作成されています。

ついでに

 
select * from schema_migrations;で問題なく情報が一つ増えていることを確認します。

tt_db=> select * from schema_migrations;
    version
----------------
 20190224051828
 20190224052935
 20190224053300
 20190224054338
 20190224055456
 20190224063318
(6 rows)

マイグレーションを実行する前は5rowsだったので問題なくできています。

そしたらデータベースから離脱して

rails db:migrate:statusでupが6つになっていることを確認します。

database: tt_db

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190224051828  Create users
   up     20190224052935  Add address to users
   up     20190224053300  Change address column
   up     20190224054338  Add birthday not null
   up     20190224055456  Add good to users
   up     20190224063318  Add height to users

次にためしにデータを作成します。

irb(main):001:0> user = User.new
=> #<User id: nil, name: nil, email: nil, password: nil, created_at: nil, updated_at: nil, address: nil, birthday: nil, password_digest: nil, good: nil, height: nil>
irb(main):002:0> user.name = "pon"
=> "pon"
irb(main):003:0> user.email = "pon@gmail.com"
=> "pon@gmail.com"
irb(main):004:0> user.password ="pon"
=> "pon"
irb(main):005:0> user.height = "180cm"
=> "180cm"
irb(main):006:0> user.save
   (0.2ms)  BEGIN
  User Create (0.7ms)  INSERT INTO "users" ("name", "email", "password", "created_at", "updated_at", "height") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"  [["name", "pon"], ["email", "pon@gmail.com"], ["password", "pon"], ["created_at", "2019-02-24 06:45:18.618771"], ["updated_at", "2019-02-24 06:45:18.618771"], ["height", "180cm"]]
   (7.5ms)  COMMIT
=> true
irb(main):007:0>

rails dbでデータベースに接続してデータを確認すると

 id | name |     email     | password |         created_at         |         updated_at         | address | birthday | password_digest | good | height
----+------+---------------+----------+----------------------------+----------------------------+---------+----------+-----------------+------+--------
  3 | pon  | pon@gmail.com | pon      | 2019-02-24 06:45:18.618771 | 2019-02-24 06:45:18.618771 |         |          |                 |      | 180cm
(1 row)

こんな感じで情報が出てきます。

ここまでしたら

rails db:rollbackで前の状態に戻します

== 20190224063318 AddHeightToUsers: reverting =================================
-- remove_column(:users, :height)
   -> 0.0007s
== 20190224063318 AddHeightToUsers: reverted (0.0013s) ========================

問題なくrollbackできるはず

rails db:migrate:statusを確認

database: tt_db

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20190224051828  Create users
   up     20190224052935  Add address to users
   up     20190224053300  Change address column
   up     20190224054338  Add birthday not null
   up     20190224055456  Add good to users
  down    20190224063318  Add height to users

一つdownになっているやつがいまrollbackしたものです。

ここでrails dbでデータベースにアクセスしてusersの情報をみてみると

tt_db=> select * from users;
 id | name |     email     | password |         created_at         |         updated_at         | address | birthday | password_digest | good
----+------+---------------+----------+----------------------------+----------------------------+---------+----------+-----------------+------
  3 | pon  | pon@gmail.com | pon      | 2019-02-24 06:45:18.618771 | 2019-02-24 06:45:18.618771 |         |          |                 |
(1 row)

heightのカラムがなくなっています。

ここまでは良いのですがこのあとまたrails db:migrateを実行すると

tt_db=> select * from users;
 id | name |     email     | password |         created_at         |         updated_at         | address | birthday | password_digest | good | height
----+------+---------------+----------+----------------------------+----------------------------+---------+----------+-----------------+------+--------
  3 | pon  | pon@gmail.com | pon      | 2019-02-24 06:45:18.618771 | 2019-02-24 06:45:18.618771 |         |          |                 |      |
(1 row)

こんな感じでheightの情報が消えています。

こんな感じでカラムが一度消えてしまうと情報も消えてしまいます。

これはカラムの内容を変更するときに特に気を付けなくてはいけないです。

emailというカラムをmailというカラムに変更したい場合に

rails g migration change_users_email_to_mail

として

class ChangeUsersEmailToMail < ActiveRecord::Migration[5.2]
  def up
          remove_column :users, :email
          add_column :users, :mail, :string
  end

  def down
          remove_column :users, :mail
          add_column :users, :email, :string
  end
end

としてmigrate rollbackが通るようにして

rails db:migrate:statusで現在の状況を確認して追加しようとしているのがdownとして問題なく入っているのを確認して

rails db:migrateを実行すると

usersテーブルの中身は

tt_db=> select * from users;
 id | name | password |         created_at         |         updated_at         | address | birthday | password_digest | good | height | mail
----+------+----------+----------------------------+----------------------------+---------+----------+-----------------+------+--------+------
  3 | pon  | pon      | 2019-02-24 06:45:18.618771 | 2019-02-24 06:45:18.618771 |         |          |                 |      |        |
(1 row)

こんな感じでmailの中身が消えた状態になってしまっています。

これが本番の環境で大切な情報が消えてしまったとなったら大変です....

なので気を付けるようにしましょう。

追記

カラム名の変更であれば

rename_columnをつかえるっぽいです。

なのでrename_columnを使えばデータは消えずに問題ないですがカラムの型を変更する場合はどうしたらよいかわからないです。

ちなみに

既にデプロイしているプロジェクトの大切な情報を含んでいるカラムを変更したい場合どうしたらよいのでしょうか?

わかる方教えてください( ;∀;)

0
2
0

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
2