Rails:为什么不能删除依赖表,如果依赖:: destroy允许?

时间:2016-03-05 13:19:56

标签: ruby-on-rails

article_id必须在图片表中,因为每篇文章都可以有很多图片。

所以Picture表看起来像这样:

id        article_id         picture

1           34              pinguin.jpg
2           56              koala.jpg
3           56              bear.jpg

我知道destroy_all(它在依赖表上实例化一个对象并调用其destroy方法并且这是一个缓慢的过程)和delete_all之间的区别,它只是简单地清除记录而不关心关联。

但我必须使用destroy_all,因为有相关的依赖记录:

Article Model
    class Article < ActiveRecord::Base
      belongs_to :user
      has_many :pictures , **`dependent: :destroy`**
      accepts_nested_attributes_for :pictures

Picture Model
    class Picture < ActiveRecord::Base
      belongs_to :article
     mount_uploader :picture, PictureUploader

     def destroy
     end

SCHEMA

 create_table "articles", force: :cascade do |t|
    t.string   "country"
    t.string   "region"
    t.string   "town"
    t.string   "street"
    t.string   "company"
    t.string   "title"
    t.text     "content"
    t.integer  "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  add_index "articles", ["user_id", "created_at"], name: "index_articles_on_user_id_and_created_at", using: :btree
  add_index "articles", ["user_id"], name: "index_articles_on_user_id", using: :btree

  create_table "pictures", force: :cascade do |t|
    t.integer  "article_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string   "picture"
  end

所以,两个命令,Article.delete_all和Article.destroy_all

提出类似的投诉

Article.destroy_all
  Article Load (0.9ms)  SELECT "articles".* FROM "articles"  ORDER BY "articles"."created_at" DESC
   (0.1ms)  BEGIN
  SQL (1.7ms)  DELETE FROM "articles" WHERE "articles"."id" = $1  [["id", 21]]
PG::ForeignKeyViolation: ERROR:  update or delete on table "articles" violates foreign key constraint "fk_rails_658164416e" on table "pictures"
DETAIL:  Key (id)=(21) is still referenced from table "pictures".
: DELETE FROM "articles" WHERE "articles"."id" = $1
   (0.2ms)  ROLLBACK


class CreatePictures < ActiveRecord::Migration
  def change
    create_table :pictures do |t|
      t.references :article, index: true, foreign_key: true

      t.timestamps null: false
    end
  end
end

更新

我尝试在迁移文件中添加on delete cascade FK,但无济于事:

我首先删除了FK,因为我必须添加限定符:on_delete :: cascade

class RemoveFkFromPictures < ActiveRecord::Migration
  def change

    remove_foreign_key :pictures, column: :article_id
  end
end

我创建了另一个迁移文件来添加FK

class AddForeignKeyToPictures1 < ActiveRecord::Migration
  def change
    add_foreign_key :pictures, :articles, on_delete: :cascade , name: :deletingarticlescascadesonpictures

  end
end

,架构如下:

add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree

  add_foreign_key "articles", "users"
  add_foreign_key "pictures", "articles", name: "deletingarticlescascadesonpictures", on_delete: :cascade
end

所以,你会认为现在好了。嗯,它不是:

  Article Load (1.3ms)  SELECT "articles".* FROM "articles"  ORDER BY "articles"."created_at" DESC
   (0.2ms)  BEGIN
  Picture Load (0.5ms)  SELECT "pictures".* FROM "pictures" WHERE "pictures"."article_id" = $1  [["article_id", 25]]
   (0.4ms)  ROLLBACK
ActiveRecord::RecordNotDestroyed: Failed to destroy the record

1 个答案:

答案 0 :(得分:1)

首先,我要感谢您的见解和善意帮助。

从你离开的地方拿走它,我告诉你我是如何解决这个问题的,这让我有2天的时间,直到今天醒来时,我想我可以尝试一下。

1)的确,写作只是依赖::在父模型中的破坏是不够的。当你真正意味着“删除,级联”时,Ruby似乎并没有真正完成“不留孤儿”的工作,被认为是“破坏”。

2)当你生成一个创建Fk的模型时,比如说user:references,它会创建一个你可以在schema.rb文件中看到的FK,但正如你所指出的那样,默认情况下是“restrict”,那个对孩子们一无所知。

3)然后我们被搞砸了。因为两者都不会破坏Herodes的事情,FK也不会。

4)您需要从迁移文件中删除FK,将其替换为带有“on delete cascade”的FK

5)你需要删除依赖于:: destroy仍然位于模型中的。

6)这样,低级数据库命令将接管并且删除进行干净和快速。