PG :: DependentObjectsStillExist:错误:无法删除表格报告,因为其他对象依赖于它

时间:2018-04-11 03:36:05

标签: ruby-on-rails postgresql heroku drop-table

给出一点背景知识。我是Ruby on Rails的新手,我正在建立一个评论网站,用户可以在其中报告评论。我玩了一个'可报告的'多态关联,然后报告表。后来我删除了“报告”表并创建了另一个报告表。早期的迁移不允许创建新的报告表迁移,因此我在迁移早期迁移的名称旁边添加了“1”。

20180311071357_create_reports_1.rb
class CreateReports1 < ActiveRecord::Migration[5.0]
  def change
    create_table :reports do |t|
      t.string :reason
      t.text :description
      t.string :email
      t.belongs_to :reportable, polymorphic: true
      t.timestamps
    end
  end
end

快进到现在。我有一段时间没有对Heroku进行生产提交,而我只是在构建应用程序。当我推送到heroku时,我收到以下错误 -

heroku run rake db:migrate --trace

Running rake db:migrate --trace on ⬢ housereview... up, run.6689 (Free)
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:migrate
   (4.0ms)  SELECT pg_try_advisory_lock(2386658352535867725);
  ActiveRecord::SchemaMigration Load (4.6ms)  SELECT "schema_migrations".* FROM "schema_migrations"

Migrating to DeleteReports1 (20180318091834)
   (1.2ms)  BEGIN
== 20180318091834 DeleteReports1: migrating ===================================
-- drop_table(:reports)
   (2.8ms)  DROP TABLE "reports"
   (2.6ms)  ROLLBACK
   (2.3ms)  SELECT pg_advisory_unlock(2386658352535867725)

rake aborted!

StandardError: An error has occurred, this and all later migrations canceled:

PG::DependentObjectsStillExist: ERROR:  cannot drop table reports because other objects depend on it

DETAIL:  constraint fk_rails_cfc8432c20 on table notes depends on table reports

HINT:  Use DROP ... CASCADE to drop the dependent objects too.
: DROP TABLE "reports"
...
/app/bin/bundle:3:in `load'
/app/bin/bundle:3:in `<main>'

Caused by:
ActiveRecord::StatementInvalid: PG::DependentObjectsStillExist: ERROR:  cannot drop table reports because other objects depend on it

DETAIL:  constraint fk_rails_cfc8432c20 on table notes depends on table reports

HINT:  Use DROP ... CASCADE to drop the dependent objects too.
: DROP TABLE "reports"
/app/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/postgresql/database_statements.rb:98:in `async_exec'

.......
/app/bin/bundle:3:in `load'
/app/bin/bundle:3:in `<main>'

Caused by:
PG::DependentObjectsStillExist: ERROR:  cannot drop table reports because other objects depend on it

DETAIL:  constraint fk_rails_cfc8432c20 on table notes depends on table reports

HINT:  Use DROP ... CASCADE to drop the dependent objects too.
/app/vendor/bundle/ruby/2.3.0/gems/activerecord-5.0.6/lib/active_record/connection_adapters/postgresql/database_statements.rb:98:in `async_exec'

这是我的架构 -

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

  create_table "locations", force: :cascade do |t|
    t.string "address"
    t.string "street_number"
    t.string "locality"
    t.string "postal_code"
    t.string "country"
    t.string "route"
    t.string "state"
  end

  create_table "notes", force: :cascade do |t|
    t.text     "description"
    t.integer  "report_id"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
    t.index ["report_id"], name: "index_notes_on_report_id"
  end

  create_table "reports", force: :cascade do |t|
    t.string   "reason"
    t.text     "description"
    t.integer  "user_id"
    t.integer  "review_id"
    t.datetime "created_at",   null: false
    t.datetime "updated_at",   null: false
    t.datetime "completed_at"
    t.index ["review_id"], name: "index_reports_on_review_id"
  end

  create_table "reviews", force: :cascade do |t|
    t.string   "title"
    t.string   "duration"
    t.text     "positive"
    t.text     "negative"
    t.integer  "location_id"
    t.integer  "user_id"
    t.integer  "rating_safety"
    t.integer  "rating_neighbour"
    t.integer  "rating_owner"
    t.integer  "rating_school"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "rating_overall"
    t.boolean  "blocked"
    t.index ["location_id"], name: "index_reviews_on_location_id"
  end

  create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "",    null: false
    t.string   "encrypted_password",     default: "",    null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,     null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.string   "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string   "unconfirmed_email"
    t.datetime "created_at",                             null: false
    t.datetime "updated_at",                             null: false
    t.boolean  "admin",                  default: false
    t.string   "first_name"
    t.string   "last_name"
    t.string   "locality"
    t.string   "state"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

我尝试了(几乎)解决问题的一切。以下我到目前为止尝试过的事情 - - 删除了生产应用程序,然后恢复pgbackup - 删除生产应用程序,然后尝试做一个新的'git push heroku master',然后'heroku run rake db:migrate' - 尝试drop table命令然后再次推送代码并rake db:migrate - 尝试'DROP TABLE if exists reports cascade;'在pgsql

以上所有都没有运气。 该应用程序在开发(SQLite)中工作得很好,但heroku不让我责备db:migrate。

提前致谢!

2 个答案:

答案 0 :(得分:1)

Notes表包含report_id作为外键,因此您无法删除报表。你可以使用dependent: :destroy来做 在report.rb文件更改行

has_many :notes

has_many :notes, dependent: :destroy 

答案 1 :(得分:0)

您是否还有创建notes表格的迁移?我猜测该迁移中的create_table :notes与您在db/schema.rb中看到的内容不完全匹配。

无论如何,您的问题是notes.report_id通过数据库中的外键引用reports.id。此外键可能是由迁移中的t.references :report, foreign_key: true创建的,以确保参照完整性(即数据库将确保notes.report_id中的任何值引用reports表中的某些内容。此外键约束阻止您删除reports表,因为这会违反notes.report_id上的约束。

我认为你根本不想删除reports表。相反,您希望Heroku的reports表与schema.rb所说的匹配。迁移并不意味着永远持续下去,所以继续删除有问题的迁移并编写一个新的迁移,使Heroku的reports表与schema.rb所说的同步。

一旦你清理了这个混乱,你有两件事要做:

  1. 永远不要再重命名迁移。删除旧迁移并立即添加新迁移。如果你想保留一个旧版本,但是将其名称用于其他内容,那么在 new 迁移上添加一个后缀,但实际上,没有理由永远保留旧的迁移。

  2. 在本地开发环境中安装PostgreSQL。您应始终使用相同的堆栈进行开发,测试和部署。数据库之间存在很多差异,ActiveRecord无法保护您免受在三种环境中使用不同数据库的困扰,这只是一种疯狂,只不过是对痛苦和苦难的简短描述。