Rails 5.2错误更改或删除表列(SQLite3 :: ConstraintException:FOREIGN KEY约束失败:DROP TABLE)

Liz*_*Liz 8 sql sqlite ruby-on-rails

我正在尝试完成从我的Blog表中更改其中一列的默认值的相当简单的壮举.我有以下迁移:

class UpdateBlogFields < ActiveRecord::Migration[5.2]
  def change
    change_column :blogs, :freebie_type, :string, default: "None"
  end
end
Run Code Online (Sandbox Code Playgroud)

相当简单,但运行时出现以下错误rake db:migrate:

StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::ConstraintException: FOREIGN KEY constraint failed: DROP TABLE "blogs"
Run Code Online (Sandbox Code Playgroud)

我在尝试更改或删除列时会收到此错误,但在添加列时则不会收到此错误.

我的架构如下所示:

  create_table "blogs", force: :cascade do |t|
    t.string "title"
    t.string "teaser"
    t.text "body"
    t.string "category", default: "General"
    t.string "linked_module"
    t.boolean "published", default: false
    t.datetime "published_on"
    t.integer "user_id"
    t.integer "image_id"
    t.integer "pdf_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "slug"
    t.string "cta_read_more", default: "Read More"
    t.string "cta_pdf", default: "Get My Free PDF"
    t.string "cta_video", default: "Watch the Video"
    t.string "convertkit_data_form_toggle"
    t.string "convertkit_href"
    t.integer "pin_image_id"
    t.string "data_pin_description"
    t.string "freebie_filename"
    t.string "video_link"
    t.string "freebie_type", default: "File"
    t.string "freebie_description"
    t.integer "comments_count"
    t.integer "subcategory_id"
    t.boolean "affiliate_links", default: true
    t.boolean "approved", default: false
    t.boolean "submitted", default: false
    t.index ["image_id"], name: "index_blogs_on_image_id"
    t.index ["pdf_id"], name: "index_blogs_on_pdf_id"
    t.index ["pin_image_id"], name: "index_blogs_on_pin_image_id"
    t.index ["slug"], name: "index_blogs_on_slug", unique: true
    t.index ["subcategory_id"], name: "index_blogs_on_subcategory_id"
    t.index ["user_id"], name: "index_blogs_on_user_id"
  end
Run Code Online (Sandbox Code Playgroud)

看起来这可能是一个SQLite的东西,因为这个帖子这个似乎有类似的问题.但是,这两篇文章都没有涉及实际答案.有没有人成功摆脱这个?

Tom*_*Tom 5

更新:

可以通过Rails添加新的默认列,而不必使用数据库。在Blog模型中,我们可以使用ActiveRecord :: Attributes :: ClassMethods :: attribute重新定义默认值freebie_type

attribute :freebie_type, :string, default: 'None'

这将在业务逻辑级别更改默认值。因此,它取决于使用ActiveRecord进行识别。通过SQL操作数据库仍将使用旧的默认值。要在所有情况下更新默认设置,请参见下面的原始答案。

原始答案:

不幸的是,SQLite ALTER COLUMN仅提供了最低限度的支持。解决该问题的方法是创建一个新表,将信息复制到其中,删除旧表,最后重命名新表。这是Rails试图做的,但是没有首先禁用外键约束。与user_idimage_id和的外键关系pdf_id阻止了表的删除。

您将需要使用SQL(首选)或手动进行更新ActiveRecord::Base.connection。您可以在此处的 “修改表中的列”下看到该过程。您可以在SQLite创建表文档中找到所有可用于列的选项。

PRAGMA foreign_keys=off;

BEGIN TRANSACTION;

ALTER TABLE table1 RENAME TO _table1_old;

CREATE TABLE table1 (
( column1 datatype [ NULL | NOT NULL ] DEFAULT (<MY_VALUE>),
  column2 datatype [ NULL | NOT NULL ] DEFAULT (<MY_VALUE>),
  ...
);

INSERT INTO table1 (column1, column2, ... column_n)
  SELECT column1, column2, ... column_n
  FROM _table1_old;

COMMIT;

PRAGMA foreign_keys=on;
Run Code Online (Sandbox Code Playgroud)

请确保您已按照自己的方式设置了所有列,因为创建表后将无法对其进行修复!展望未来,我强烈建议您设置PostgreSQL或MySQL2数据库。它们功能更强大,修改和维护也更容易。