如果涉及外键,如何在Rails 5中重做迁移?

时间:2017-09-30 17:29:08

标签: ruby-on-rails ruby

所以我在这里遇到了一些相关的问题。所以我已经开始将主题添加回我的应用程序。但是,当我尝试创建一个新帖子时,我得到“主题必须存在”。我不确定具体要做什么是缺少的。

我知道我需要以某种方式重做

AddTopicReferenceToBlogs迁移,因为现在我的博客表看起来像这样:

create_table "blogs", force: :cascade do |t|
    t.string "title"
    t.text "body"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "slug"
    t.integer "status", default: 0
    t.index ["slug"], name: "index_blogs_on_slug", unique: true
  end

缺少t.integer“topic_id”。

我知道我无法重新运行AddTopicReferenceToBlogs,因为我会得到相同的内容。

如果我尝试执行rake db:migrate:down VERSION =

我收到此错误:

== 20170725215733 AddTopicReferenceToBlogs: reverting =========================
-- remove_reference(:blogs, :topic, {:foreign_key=>true})
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
Table 'blogs' has no foreign key for {:to_table=>"topics", :column=>"topic_id"}

顺便说一句,我的Topic.rb文件如下所示:

class Topic < ApplicationRecord
 validates_presence_of :title
end

2 个答案:

答案 0 :(得分:0)

你的问题没有快速的答案,但我认为有助于你理解你可以重做AddTopicReferenceToBlogs,你只需要给它一个不同的名字。

本文档说明了这一点: Rails migrations with the same name

尝试类似:

rails g migration add_reference_of_topic_to_blogs topic:references

假设您还没有搞砸过程中的其他迁移,那应该可行。如果您不确定自己在做什么,Rails迁移会变得非常毛茸茸。

答案 1 :(得分:0)

如果在开发环境中无法正确执行,则可能仍有问题。

rails db:drop db:create db:migrate db:seed

如果您刚刚添加了新迁移以修复旧迁移,则此完整数据库重置可能会失败,因为您现在尝试重复迁移add_reference :blogs, :topic, ...。这对您的队友和部署到生产时都是一个问题。

假设:

  1. 您生成了名为AddTopicReferenceToBlogs的空迁移,并使用rails db:migrate(或rake db:migrate)进行了迁移。

  2. 之后检查schema.rb时,您希望在那里的外键(topic_id)不是。

  3. 您编辑了空迁移,以添加使用add_reference并再次运行rails db:migrate的行。

  4. 架构仍未包含blogs.topic_id

  5. 您尝试使用rake db:migrate:down VERSION=???回滚迁移,但失败了(...因为您尝试回滚从未实际运行的迁移.Rails无法删除它从未添加的引用开始用)。

  6. 答案:

    1. 请勿添加执行相同操作但具有不同类名的重复迁移。

    2. 在错误迁移add_reference中注释掉AddTopicReferenceToBlogs行。

    3. 回滚空迁移(撤消你做的坏事)。

    4. 重新激活add_reference行。

    5. 再次
    6. rake db:migrate,这次正确地将您期望的外键添加到schema.rb

    7. 将来,使用此命令为这些类型的关联生成预先填写的迁移。

      rails g migration AddTopicToBlog topic:belongs_to
      

      备选方案:

      rails g migration AddTopicToBlogs topic:belongs_to
      rails g migration AddTopicToBlog topic:references
      rails g migration AddYouCanSayWhateverYouWantHereToBlog topic:references