2016-03-05 86 views
3

article_id位于Pictures图表中,因为它必须是,因为每个文章都可以有很多图片。Rails:为什么不能删除依赖表如果依赖:: destroy允许?

所以图像表是这样的:

id  article_id   picture 

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

我知道(destroy_all之间的差异,其实例的相关表的对象,并调用其销毁方法,它是一个缓慢进程)和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 

UPDATE

我曾试图迁移文件添加上删除级联FK,不得要领:

我第一次删除的FK因为我不得不添加了预选赛:on_delete:级联

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 
+0

那些**不在你的模型中,你只是用它们来突出显示。你可以创建一个级联删除的fk。全部取决于你是否想让rails删除它或数据库。 – Doon

+0

http://stackoverflow.com/questions/29544693/cant-delete-object-due-to-foreign-key-constraint/29544875#29544875 – Doon

+0

您需要自己编写迁移代码。发电机不会为你做。 – Doon

回答

1

首先我想感谢您的洞察力和善意帮助。

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

1)确实,在Parent模式下编写只依赖于::destroy是不够的。看来,当你实际上的意思是“关于删除,级联”时,Ruby实际上并没有做“不留下孤儿”的工作,认为这是由“摧毁”表示的。

2)当您生成创建Fk的模型时,比如说user:references,它确实会创建一个FK,您可以在schema.rb文件中看到该FK,但正如您所指出的,默认情况下为“restrict”也就是说,对孩子什么都不做。

3)然后我们拧紧。因为既不会破坏Herodes的东西,也不会破坏FK。

4)你必须从迁移文件中删除FK,由FK有“ON DELETE CASCADE”

5更换),您需要删除相关:摧毁它仍然坐在模型中。

6)通过这种方式,低级别的数据库命令将接管,并且删除过程会干净而快速。