PG::DependentObjectsStillExist: ОШИБКА: нельзя удалить отчеты таблицы, поскольку от нее зависят другие объекты

дать немного фона. Я новичок в 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 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» - Попытался удалить table , а затем снова нажмите код и rake db: migrate - попробовал «УДАЛИТЬ ТАБЛИЦУ, если существует каскад отчетов;» в pgsql

Все вышеперечисленное не повезло. Приложение отлично работает в dev (SQLite), но heroku не позволяет мне разгребать db:migrate.

Заранее спасибо!


person F A    schedule 11.04.2018    source источник


Ответы (2)


Таблица Notes содержит report_id в качестве внешнего ключа, поэтому вы не можете удалить таблицу отчетов. Вы можете сделать это, используя dependent: :destroy В файле report.rb изменить строку ниже

has_many :notes

to

has_many :notes, dependent: :destroy 
person darshi kothari    schedule 11.04.2018
comment
@FA Вы можете сгенерировать одну миграцию для удаления report_id из таблицы заметок и создать эту миграцию перед миграцией отбрасываемой таблицы. так что эта миграция удалит report_id из таблицы заметок, а затем вы можете удалить таблицу отчетов - person darshi kothari; 11.04.2018

У вас все еще есть миграция, которая создала таблицу 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. Вместо этого вы хотите, чтобы таблица reports в Heroku соответствовала тому, что говорит schema.rb. Миграции не должны длиться вечно, так что действуйте и удалите оскорбительные миграции и напишите новую, которая синхронизирует таблицу reports в Heroku с тем, что говорит schema.rb.

После того, как вы уберете этот беспорядок, вам нужно сделать две вещи:

  1. Никогда больше не переименовывайте миграции. Удаляйте старые миграции и время от времени добавляйте новые. Если вы хотите сохранить старую версию, но использовать ее имя для чего-то другого, добавьте суффикс к новой миграции, но на самом деле нет причин хранить старые миграции вечно.

  2. Установите PostgreSQL в вашей локальной среде разработки. Вы всегда должны разрабатывать, тестировать и развертывать с одним и тем же стеком. Существует так много различий между базами данных, что ActiveRecord не защитит вас от этого, использование разных баз данных в трех средах — это безумие и не более чем кратчайший путь к боли и страданиям.

person mu is too short    schedule 11.04.2018
comment
Последние два совета — золотые. Моему младшему на 6 месяцев нужно было поговорить с вами раньше. Я думаю, что я понимаю ошибку, которую я сделал, и поправьте меня, если я ошибаюсь. 1) Я создал таблицу reports, затем создал таблицу notes. 2) reports и notes имели связь 1-ко-многим. 3) Я нажал на Heroku. 4) Затем я удалил свою таблицу reports в среде разработки. 5) Затем я воссоздал таблицу reports. 6) Нажатие Heroku теперь показывает ошибку, потому что таблица notes ссылается на предыдущую таблицу отчетов? решение- удалить report_id и заново создать столбец report_id в таблице notes? - person F A; 11.04.2018
comment
Это звучит правильно. Если вам не нужны данные, удаление столбца notes.report_id также удалит FK. Вы должны сделать это при миграции перед удалением таблицы reports. - person mu is too short; 11.04.2018
comment
все равно не повезло. получить ту же ошибку. Я удалил обе таблицы reports и notes. И все еще получаю эту ошибку - == 20180318091834 DeleteReports: migrating ==================================== -- drop_table(:reports) (2.9ms) DROP TABLE "reports" (0.6ms) ROLLBACK 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 - person F A; 13.04.2018
comment
Вы можете вручную connection.execute('alter table notes drop constraint fk_rails_cfc8432c20') в крайнем случае. Вы также можете удалить проблемные миграции, просмотреть структуру таблицы в рабочей среде, а затем добавить новую миграцию для их синхронизации. - person mu is too short; 13.04.2018