2016-03-05 54 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)通過這種方式,低級別的數據庫命令將接管,並且刪除過程會乾淨而快速。