ActiveRecordのMigrationを単体で使う
85,000番煎じです。
Railsについての知識がないのですが、よく見かけるコマンドrake db:migrate
。
これがめっちゃ便利で、かつ非RailsなアプリでもActiveRecord単体で使えるらしいので使ってみた。
どうでもいいですがmigrate
は移動とか移住って意味です。なるほど。
ディレクトリ、ファイルの準備
ガシガシとコマンドを投入していく。
mkdir -p db/migrate touch db/migrate/001_create_samples.rb touch db/migrate/002_add_tag_for_samples.rb touch Rakefile
とりあえず空ファイルができた。
migration用のファイルを編集
例として作成するテーブルの構成は以下のような感じ。
- テーブル名
- samples
- カラム
- id(pk)
- body(varchar)
- tag(varchar)
001_create_samples.rb
でテーブル作成とid
, body
カラムの追加。
002_add_tag_for_samples.rb
でtag
カラムを追加したいとします。
001_create_samples.rb
は以下のように。
class CreateSamples < ActiveRecord::Migration def up create_table :samples do |t| t.string :body end end def down drop_table :samples end end
002_add_tag_for_samples.rb
は以下のように。
class AddTagForSamples < ActiveRecord::Migration def change add_column :samples, :tag, :string end end
ハマった・調べたポイントは、
- mingration用のrubyスクリプトのファイル名とclass名は紐付ける必要がある
up
,down
はそれぞれmigrateとrollback時の処理を定義するときに使う- rollbackする時の処理を書いてないと困るとき(
up
にremove_column
があったり)
- rollbackする時の処理を書いてないと困るとき(
change
はそれひとつでmigrate時に実行される処理を反転した処理をrollback時に実行してくれます
Rakefile作るぞ!
兼ねてからRake学ぶと嘯いていますが、盗みみながらようやっと書きました。
require 'active_record' require 'yaml' namespace :db do migrate_dir = 'db/migrate' config = YAML.load_file('config/database.yml') ActiveRecord::Base.establish_connection(config['db']['development']) desc 'Migrate db' task :migrate do ActiveRecord::Migrator.migrate(migrate_dir, ENV['VERSION'] ? ENV['VERSION'].to_i : nul) end desc 'Roll back db' task :rollback do ActiveRecord::Migrator.rollback(migrate_dir, ENV['STEP'] ? ENV['STEP'].to_i : 1) end end
VERSION
とSTEP
を指定することでmigrateとrollbackの粒度を指定できるようになってます。
いざ実行!
ではさっそく実行してみましょう。
$ bundle exec rake -T rake db:migrate # Migrate db rake db:rollback # Roll back db
タスクが登録されております。
この調子でmigrateします。
$ bundle exec rake db:migrate == 1 CreateSamples: migrating ================================================= -- create_table(:samples) -> 0.0086s == 1 CreateSamples: migrated (0.0087s) ======================================== == 2 AddTagForSamples: migrating ======================================================== -- add_column(:samples, :tag, :string) -> 0.0005s == 2 AddTagForSamples: migrated (0.0006s) ===============================================
ホントに処理が走ったから接続して見てみます。
$ psql -U dbuser -d testdb testdb=> \d samples Table "public.samples" Column | Type | Modifiers --------+-------------------+------------------------------------------------------ id | integer | not null default nextval('samples_id_seq'::regclass) body | character varying | tag | character varying | Indexes: "samples_pkey" PRIMARY KEY, btree (id)
できてるー!やったー!
rollbackもしてみます。
$ bundle exec rake db:rollback == 2 AddTagForSamples: reverting ======================================================== -- remove_column(:samples, :tag, :string) -> 0.0008s == 2 AddTagForSamples: reverted (0.0030s) ===============================================
testdb=> \d samples Table "public.samples" Column | Type | Modifiers --------+-------------------+------------------------------------------------------ id | integer | not null default nextval('samples_id_seq'::regclass) body | character varying | Indexes: "samples_pkey" PRIMARY KEY, btree (id)
tag
カラムが消えてますね。
ちなみに一気にrollbackしたい時はSTEP
に値を指定してやればよいです。
$ bundle exec rake STEP=2 db:rollback
所感
テーブル編集の履歴が残っていい感じっぽい。
Rakefileにmaigrationのログを吐くように処理を追記すればなおよさげ。
複数テーブルの扱いは明日やる。
謝辞
rake db:migrateで、uninitialized constant hogehoge - xengineer's diary -
【Rails】migrationのchangeとup/downって何が違うの? - tanihiro.log -
新しいマイグレーションを追加してテーブルを変更 - RubyLife -