【问题标题】:Error removing column Rails删除列 Rails 时出错
【发布时间】:2017-11-17 09:37:13
【问题描述】:

在我的 Rails 应用程序中,我有一个名为 Rutinas 的模型。一段时间后,我需要向表中添加一些列,因此我生成了迁移20171116094810_add_votos_y_veces_asignada_to_rutinas.rb

class AddVotosYVecesAsignadaToRutinas < ActiveRecord::Migration[5.1]
  def change
    add_column :rutinas, :votos_pos, :integer, :default => 0
    add_column :rutinas, :votos_neg, :integer, :default => 0
    add_column :rutinas, :veces_asig, :integer, :default => 0
  end
end

在其他一些迁移之后,我需要删除两个不再需要的列 votos_posvotos_neg 所以我生成了另一个迁移 20171117092026_remove_votos_from_rutinas.rb

class RemoveVotosFromRutinas < ActiveRecord::Migration[5.1]
  def change
    remove_column :rutinas, :votos_pos, :integer
    remove_column :rutinas, :votos_neg, :integer
  end
end

问题是当我运行rails db:migrate 来迁移最后一次迁移时,它会抛出一些奇怪的错误:

== 20171117092026 RemoveVotosFromRutinas: migrating ===========================
-- remove_column(:rutinas, :votos_pos)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

SQLite3::ConstraintException: FOREIGN KEY constraint failed: DROP TABLE "rutinas"
C:/Users/pepe/Dropbox/pepe/KeepMeFit/KeepMeFit-git/db/migrate/20171117092026_remove_votos_from_rutinas.rb:3:in `change'
bin/rails:4:in `require'
bin/rails:4:in `<main>'

Caused by:
ActiveRecord::InvalidForeignKey: SQLite3::ConstraintException: FOREIGN KEY constraint failed: DROP TABLE "rutinas"
C:/Users/pepe/Dropbox/pepe/KeepMeFit/KeepMeFit-git/db/migrate/20171117092026_remove_votos_from_rutinas.rb:3:in `change'
bin/rails:4:in `require'
bin/rails:4:in `<main>'

Caused by:
SQLite3::ConstraintException: FOREIGN KEY constraint failed
C:/Users/pepe/Dropbox/pepe/KeepMeFit/KeepMeFit-git/db/migrate/20171117092026_remove_votos_from_rutinas.rb:3:in `change'
bin/rails:4:in `require'
bin/rails:4:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)

我的 Rutinas 模型如下:

class Rutina < ActiveRecord::Base    
  validates_presence_of :nombre

  belongs_to :user
  has_many :repeticions
  has_many :entrenos, dependent: :destroy
  has_many :votos

  has_many :days, dependent: :destroy

  def get_array_dias
    (1..self.repeticions.last.dia).to_a
  end

  def get_number_of_days
    days.count
  end

end

User、repeticion、entreno、voto 和 day 是与我要删除的列无关的其他表。也就是说,这些列不是外键,任何外键都引用了这些列。

【问题讨论】:

  • 您能简要介绍一下您的 Rutinas 模型吗?您的 Rutinas 模型可能与另一个模型相关联。
  • 可能另一个模型在Rutinas 模型上有外键。之前删除关联模型中的外键列。
  • 你能去rails db并粘贴命令\d rutinas的输出吗?

标签: ruby-on-rails ruby rails-migrations


【解决方案1】:

问题似乎是 SQLite 的限制。如果您检查您将看到的文档,它只允许添加一列,但不能删除一列:https://sqlite.org/lang_altertable.html

当删除列时,迁移实际上可能会删除整个表并重新创建它。这将解释DROP TABLE "rutinas" 消息。当然,如果 while 表被删除,那么某些外键约束失败是有意义的。

【讨论】:

  • 在查看活动记录gem中的sqlite3_adapter.rb后,看起来该表在删除之前已被复制,因此不会丢失任何数据。如果您通过在所有 has_many 语句中添加 dependent: :destroydependent: :nullify 来满足所有约束,则迁移可能会起作用。
【解决方案2】:

它将在 Rails 6 中修复,包括 https://github.com/rails/rails/pull/32865 。这需要 SQLite 数据库 3.8 及更高版本。我认为它不会被移植到 Rails 5.2 或更早版本中。

我的回答可能不会给你任何关于如何编写代码的实际反馈,我现在可以说的是升级 Rails 6(发布日期未确定)可能会解决这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-15
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    相关资源
    最近更新 更多