RailsでMySQLにスキーマファイルからテーブルを作成してみる

RailsをMySQLに対応させてみるの続き。


最初はdb/schema.rbが無いので、
とりあえずdb:schema:dumpで、現在のデータベースからschema.rbを作成する。

$ rake db:schema:dump

下記のschema.rbが生成される。
現状、テーブルがなにも無いので、下記のような中身になる。

$ cat db/schema.rb
ActiveRecord::Schema.define(version: 0) do

end

schema.rbに下記のようなcreate_tableを追加する。

$ vi db/schema.rb
ActiveRecord::Schema.define(version: 0) do

  create_table "sample1" do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end

db:schema:loadを実行すると、

$ rake db:schema:load

sample1のテーブルが作成される。
また、スキーマのバージョンを管理するschema_migrationsのテーブルも作成される。

mysql> use sample_mysql_development;
mysql> show tables;
+------------------------------------+
| Tables_in_sample_mysql_development |
+------------------------------------+
| sample1                            |
| schema_migrations                  |
+------------------------------------+

create_tableは下記のように複数指定できる。

ActiveRecord::Schema.define(version: 0) do

  create_table "sample1" do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "sample2" do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end

ただ、今の状態でdb:schema:loadを実行すると、すでにsample1のテーブルが存在するため、エラーになる。

$ rake db:schema:load
-- create_table("sample1")
rake aborted!
Mysql2::Error: Table 'sample1' already exists: CREATE TABLE `sample1` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, `created_at` datetime, `updated_at` datetime) ENGINE=InnoDB
/home/dev/sample_mysql/db/schema.rb:16:in `block in <top (required)>'
/home/dev/sample_mysql/db/schema.rb:14:in `<top (required)>'
Tasks: TOP => db:schema:load
(See full trace by running task with --trace)

forceオプションでtrueを指定すると、すでに存在していても
削除して作りなおす。

ActiveRecord::Schema.define(version: 0) do

  create_table "sample1", force: true do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "sample2", force: true do |t|
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end
$ rake db:schema:load
-- create_table("sample1", {:force=>true})
   -> 0.0390s
-- create_table("sample2", {:force=>true})
   -> 0.0087s
-- initialize_schema_migrations_table()
   -> 0.0027s

また、db:resetだと、内部では
・db:drop
・db:create
・db:schema:load
が実施され、DBが作り直されるので、forceを指定してなくても初期化される。

$ rake db:reset

ただ、本来は、schema.rbを直接修正してテーブルを作成することはなく、migrationでテーブルを作成し、自動でschema.rbが生成されるのが一般的っぽい。