#author("2019-10-12T07:54:36+00:00","default:wikiwriter","wikiwriter")
#author("2022-06-24T04:41:02+00:00","default:src128","src128")
&tag(マイグレーション);
*目次 [#v5671532]
#contents
*関連ページ [#dd30858c]
-[[Rails]]

*参考情報 [#f8d1da54]

*マイグレーションファイルの作成 [#f2f4eb5f]

**マイグレーションファイルの単体作成 [#t8235a17]
- 「rails generate migration マイグレーション名」で生成可能。[[NAMAKESUGI |[Rails4] migrationコマンドまとめ:http://namakesugi.blog42.fc2.com/blog-entry-157.html]]
- createから始めたらcreate table、addから始めたらカラムの追加、removeから始めたらカラムの削除用のテンプレートを自動で作ってくれる。
-[[Rails4のマイグレーションの書き方まとめ | @cyber_yoshida:http://hyoshida.github.io/2014/12/27/writting-a-migration-in-rails-4.html]]によると、"change"にまとめる方向になっていて、"self.up"や"self.down"はなくなりインスタンスメソッドの"up"や"down"に変更されている。
-属性を変更する場合やカラムを削除する場合はchangeでreversibleを使って記述するか、インスタンスメソッドのup、downに記述する

*** テーブル生成 [#t4d00d54]
-booksテーブルを生成する場合以下のコマンドを実行する。
 bundle exec rails generate migration create_books
-ファイルを書き換える
#pre{{
class CreateHoges < ActiveRecord::Migration
  def change
    create_table :hoges do |t|
      t.string :name
      t.integer :age
      t.timestamps
    end
  end
end
}}


*** テーブルに文字列カラムを追加する [#ib05cf4e]
-booksテーブルにimageカラム(文字列)を追加する
 bundle exec rails generate migration add_image_to_books
-ファイルを書き換える
#pre{{
class AddImageToBooks < ActiveRecord::Migration
  def change
    add_column :books, :image, :string
  end
end

}}

***テーブルの型を変更する [#b9abd1d6]
-booksテーブルのtitleをstringからtextに変更する
 bundle exec rails generate migration change_title_type_of_books
-マイグレーションファイルを編集する
#pre{{
class ChangeTitleTypeOfBooks < ActiveRecord::Migration
  def change
    change_column :books, :title, :text
  end
end
}}

***テーブルにインデックスを追加する [#zf93952a]
-accessesテーブルのdateカラムにインデックスを追加する
 bundle exec rails generate migration add_date_index_to_accesses
-マイグレーションファイルを編集する
#pre{{
class AddDateIndexToAccesses < ActiveRecord::Migration
  def change
    add_index :accesses, :date
  end
end
}}

**テーブルに複合インデックスを追加する [#v7dbb8f4]
-複合インデックスの指定方法
#pre{{
class AddDateIndexToAccesses < ActiveRecord::Migration
  def change
    add_index :accesses, [:date, :key]
  end
end
}}

*** テーブルにMySQLのLONGTEXTカラムを追加する [#d856bcf4]
-":text"だけだとLONGTEXTにならない。, :limitが必要。[[コチョナナバ: railsでmysqlのlongtext型を使う:http://kingyo-bachi.blogspot.jp/2013/06/railsmysqllongtext.html]]
#pre{{
class AddDescriptionToBooks < ActiveRecord::Migration
  def change
    add_column :books :description, :text, :limit => 4294967295
  end
end
}}

***カラムのデフォルト値を設定する [#l8d14b64]
-migrationファイル中でadd_columnした後、updateなどでデフォルト値を設定したい場合、reset_column_informationが必要っぽい。
#pre{{
    add_index :feeds, :folder_id
    Feed.reset_column_information
    #フィードのfolder_idのデフォルト設定
    Feed.where(:feed_provider_id => 1).update_all(:folder_id => 999)
}}
**モデルファイル込みで生成 [#s3b2da4d]
-bundle exec rails g model モデル名 カラム定義…で生成する。
 bundle exec rails g model product name:string price:integer

**モデルコントローラービュー込みで生成 [#h16f3094]
-bundle exec rails g scaffold モデル名 カラム定義…で生成する。
 bundle exec rails g scaffold product name:string price:integer

**マイグレーションファイルのバージョン指定 [#s4e1a856]
-Rails 5からMigrationファイルにバージョンが指定できるようになった
#pre{{
class AddUrlToFeeds < ActiveRecord::Migration[5.0]
  def change
  end
end
}}
-これによってRailsのバージョン毎のルールにのっとったマイグレーションが実行できるようになる。
-例えばRails 5.0では主キーがIntだがRails 5.1ではデフォルトでBigIntになるなど。
--[[Rails 5.1以前に作成されたテーブルにFK制約を張れない問題の解決策:https://qiita.com/nametaketakewo/items/d9d26fb301a09d7e6c2c]]
--[[Rails 5から導入されたmigration versioingについて | 日々雑記:http://y-yagi.tumblr.com/post/137935511450/rails-5%E3%81%8B%E3%82%89%E5%B0%8E%E5%85%A5%E3%81%95%E3%82%8C%E3%81%9Fmigration-versioing%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6]]
--[[Rails 5.1にスムーズにアップグレードするためにやった6つのこと:https://tech.medpeer.co.jp/entry/2017/07/18/064500]]…BigIntではなくIntを使い続けたい場合。


*マイグレーションファイルの削除 [#f77af3b7]
-[[railsのrakeで作成したmigrationファイルとstatus履歴を削除する – joppot:https://joppot.info/2014/10/14/2073]]
-一度作成したけど不要になった場合。
-以下のコマンドで削除する。up状態で実行してもうまくいく?
 bundle exec rails destroy migration マイグレーションクラス名
 bundle exec rails destroy migration マイグレーションファイル名(create_index_entriesとか)
-もしくはrollbackしてdown状態で手動でマイグレーションファイルを削除すればいいらしい。
*マイグレーション実行 [#be4a52be]

**通常実行 [#n1cd69c5]
-マイグレーション実行。何も指定しないとdevelopment環境が更新される。
 bundle exec rake db:migrate

**環境を指定して実行 [#p7792130]
-production環境を更新したい場合
 bundle exec rake db:migrate RAILS_ENV=production

**戻す [#r50b0142]
-rollbackを指定する
 bundle exec rake db:rollback

**マイグレーションを再実行 [#u613f246]
-DB削除、DB作成、マイグレーションを全部実行する。
 bundle exec rake db:migrate:reset
-現在のスキーマに基いて実行したい場合は以下のコマンド。
 bundle exec rake db:reset

現在の状態に基いてテーブルを作り直したい場合「db:reset」じゃないとだめ。手作業でテーブル定義を修正していてマイグレーションファイルが不完全な場合、db:resetじゃないとおかしなことになる。[[DBをリセットするrakeタスク二つ - maeshimaの日記:http://maeshima.hateblo.jp/entry/20100412/1271058806]]

**マイグレーションをスキップ [#zbd4e94b]
-Pending状態になっているマイグレーションファイルをスキップしたい場合がある。
-[[ruby on rails - How do you skip failed migrations? (rake db:migrate) - Stack Overflow:http://stackoverflow.com/questions/8810732/how-do-you-skip-failed-migrations-rake-dbmigrate]]によると、専用のインターフェイスは存在せず、schema_migrationsテーブルにスキップしたいマイグレーションファイルの数字をINSERTするしかない?
-[[Railsでマイグレーションを介さずにサーバーでDBを変更してしまったとき - PILOG:http://xoyip.hatenablog.com/entry/2014/07/07/203000]]でも同様。


手順
-マイグレーションの番号を取得。downとなっているのが適用されていないものなのでそこからスキップしたい番号を選択する。
 bundle exec rake db:migrate:status
-sqlを実行する
 INSERT INTO schema_migrations (version) VALUES(20131031113857);
**schema.rbの作成 [#i0c9e9ac]
-現在のDBからschema.rbを作成したい場合
 bundle exec rake db:schema:dump
*状態確認 [#scebff42]
**マイグレーションの適用状態を確認する [#c6592d1b]
-db:migrate:statusで現在の状態を確認できる。Statusがupのところが実行済みのもの。
#pre{{
$ bundle exec rake  db:migrate:status

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20140927082920  Create books
   up     20140927084708  Create hoges
   up     20141121060148  Create software infos
   down    20150409052819  Create settings
}}
-db:versionで現在どこまで進んでいるかを確認できる。
#pre{{
$ bundle exec rake  db:version
Current version: 20141121060148
}}
**現在のdbバージョンを確認する [#p9b4f5c9]
-db:versionで確認できる。
 Current version: 20141208044134


*Tips [#h76d2731]

**マイグレーションファイルをまとめる [#rabcdba9]
-[[Railsのマイグレーションファイルを既存のスキーマ、データベースを元に作成|WEBデザイン Tips:http://blog.digital-squad.net/article/398190260.html]]で説明されている手法が使えるかも。
-schema.rbとデータベースの内容が食い違っていて、schema.rbが正しい場合以下を実行してデータベースを更新する
 bundle exec rake db:schema:load
-既存のデータベースからschema.rbを生成
 bundle exec rake db:schema:dump
-マイグレーションファイルの作成。マイグレーションファイルにschema.rbの内容を反映しておく。
 bundle exec rails g migration create_tables
-マイグレーション実行
 bundle exec rake db:migrate

※schema:dumpだとテーブルの情報が一部抜け落ちてしまう場合があるので、手動マイグレーションファイルを保存しておいたほうが安全だと思う(MySQLの場合全文検索テーブルの指定とかFT4)。
*トラブルシューティング [#e7bf77ea]

** migrationの状態を確認したらNO FILEと表示された [#cb916a47]
-該当するマイグレーションファイルが存在しない場合「rake db:migrate:status」でNO FILEと表示されてしまう。
-この場合該当するダミーマイグレーションファイルを以下の内容で作成し(例: 999がNO_FILEのIDの場合、999_tmp.rb)。
#pre{{
class Tmp < ActiveRecord::Migration
  def change
  end
end
}}
-down状態に変更
 bundle exec rake db:migrate:down VERSION=999
-999_tmp.rbを削除する。


**MyISAMテーブルがschema.rbに反映されない [#k9bc12fa]
-どうやら仕様らしい。
-schema.rbだけに頼らず、マイグレーションファイルを一つにまとめ、全部のテーブルを生成するマイグレーションファイルをメンテしておいたほうがよいかも。
-もしくはschema.rbのかわりにsqlとして管理する方法もあるらしい。

**Rails 5でbundle exec rake db:resetでエラー [#aa099f32]
-本番か今日から取り込んだデータで以下のコマンドを実行すると「ActiveRecord::ProtectedEnvironmentError」が表示される。
  RAILS_ENV=development bundle exec rake db:reset
-Rails 5だと情報がテーブルに保存されていてそれが原因らしい。[[Rails5のproductionでrake db:dropはできない、普通には - Qiita:http://qiita.com/Esfahan/items/75ade0233fe02ab04381]]。
-以下のコマンドで設定する。
 bundle exec rails db:environment:set RAILS_ENV=development
 RAILS_ENV=development bundle exec rake db:reset


**Directly inheriting from ActiveRecord::Migration is not supported. [#ydce373e]
-Rails 5からMigrationクラスにバージョンを指定する必要ができた。
-マイグレーションファイルを作成した際の正確なバージョンを指定する必要がある?
-面倒な場合、本番のデータをmysqldumpなどでまるまるコピーすれば回避できる

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS