如果我在`rake db:schema:load`之后立即运行`rake db:migrate`,为什么会修改schema.rb?

时间:2018-08-16 05:27:04

标签: ruby-on-rails mariadb database-migration

问题摘要:

我克隆了一个名为DMP Roadmap的开源项目,并按照其安装指南进行操作,直到rake db:schema:load

然后我执行rake db:migrate,该命令在终端中不产生任何输出,但是我注意到schema.rb文件已被修改。我认为这不会发生,因为rake db:migrate不会产生任何输出,这应该意味着什么都不会改变,但是架构文件会改变。

下面一定有事情发生,任何知道DB迁移的细节的人都可以解释一下下面发生了什么吗?

复制步骤:

在Mac OS上,brew install mariadb(brew info mariadb表示:稳定版10.3.9(瓶装))

关注installation guide

git clone https://github.com/DMPRoadmap/roadmap.git
cd roadmap
cp config/database_example.yml config/database.yml
cp config/secrets_example.yml config/secrets.yml
cp config/branding_example.yml config/branding.yml
cp config/initializers/devise.rb.example config/initializers/devise.rb
cp config/initializers/recaptcha.rb.example config/initializers/recaptcha.rb
cp config/initializers/wicked_pdf.rb.example config/initializers/wicked_pdf.rb
bundle install
rake secret
vi config/secrets.yml # put the secret generated above into `config/secret.yml`
rake db:create
rake db:schema:load
rake db:migrate

执行rake db:migrate后的部分git diff:

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

   create_table "annotations", force: :cascade do |t|
-    t.integer  "question_id"
-    t.integer  "org_id"
-    t.text     "text"
-    t.integer  "type",        default: 0, null: false
+    t.integer  "question_id", limit: 4
+    t.integer  "org_id",      limit: 4
+    t.text     "text",        limit: 65535
+    t.integer  "type",        limit: 4,     default: 0, null: false
     t.datetime "created_at"
     t.datetime "updated_at"
   end

-  add_index "annotations", ["question_id"], name: "index_annotations_on_question_id"
+  add_index "annotations", ["org_id"], name: "fk_rails_aca7521f72", using: :btree
+  add_index "annotations", ["question_id"], name: "index_annotations_on_question_id", using: :btree

   create_table "answers", force: :cascade do |t|
-    t.text     "text"
-    t.integer  "plan_id"
-    t.integer  "user_id"
-    t.integer  "question_id"
+    t.text     "text",         limit: 65535
+    t.integer  "plan_id",      limit: 4
+    t.integer  "user_id",      limit: 4
+    t.integer  "question_id",  limit: 4
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.integer  "lock_version", default: 0
+    t.integer  "lock_version", limit: 4,     default: 0
   end

-  add_index "answers", ["plan_id"], name: "index_answers_on_plan_id"
-  add_index "answers", ["question_id"], name: "index_answers_on_question_id"
+  add_index "answers", ["plan_id"], name: "index_answers_on_plan_id", using: :btree
+  add_index "answers", ["question_id"], name: "index_answers_on_question_id", using: :btree
+  add_index "answers", ["user_id"], name: "fk_rails_584be190c2", using: :btree

   create_table "answers_question_options", id: false, force: :cascade do |t|
-    t.integer "answer_id",          null: false

其他问题:

  • 为什么要增加一堆限制和btree?
  • 为什么要添加以下行:+ add_index "annotations", ["org_id"], name: "fk_rails_aca7521f72", using: :btree?以前没来过

1 个答案:

答案 0 :(得分:2)

您的db/schema.rb文件代表Rails看到的数据库结构。每当您执行任何可能更改数据库的操作时,Rails都会查询数据库的当前结构并将该结构写入db/schema.rb

Rails无法知道迁移是否会改变数据库的结构。如果您仅坚持使用通常的迁移助手,那么从理论上讲,它可以知道模式是否已更改,但是总有connection.execute可以将SQL直接发送到数据库。构建schema.rb相对较快,因此最简单(也是最明智的)解决方案是每次rake db:migrate都重新构建它。

更改自:

t.integer  "question_id"

t.integer  "question_id", limit: 4

建议原始schema.rb来自PostgreSQL(不支持整数列上的:limit选项),而您的用户来自MariaDB(整数列中有:limit个) )。其他更改具有相同的来源:PostgreSQL以一种方式执行操作,MariaDB以另一种方式执行操作。


我需要的不仅仅是评论,而是为一些评论者澄清一些事情。

MariaDB(MySQL的一个分支,使Oracle远离Oracle)支持btree索引,在这种特定情况下,fk_rails_584be190c2名称表明它与MariaDB(或ActiveRecord)的方式联系在一起MariaDB)处理外键。如果您查看bottom of the original schema.rb

add_foreign_key "annotations", "orgs"
...
add_foreign_key "answers", "users"
...

answers.users上的FK与名为fk_rails_584be190c2的btree索引匹配。 FK通常具有与之关联的索引,以使检查参照完整性更为有效。也许ActiveRecord / MariaDB是自动创建它们的,也许MariaDB是自己完成的。我不是MySQL或MariaDB专家,所以我不知道。