在刪除一筆model資料時,如果要連有關聯到的model的資料一起刪除時可以用dependent: :destroy
has_many :group_users , dependent: :destroy
這樣設定的話當group的資料被刪除時,對應到的group_users會跟著一起刪除
因為我自己想要手動來刪除資料所以就用了delete_all
跟destroy_all
,順便試一下兩個method的差別
然後就發現了這個delete_all的bug
要達成這個bug首先要把has_many
的dependent
參數拿掉變成
has_many :group_users
這邊我先用destroy_all來刪除(實際操作的時候我是先用pry中斷,然後直接在pry的console裡執行刪除的code)
def destroy
@group = current_user.groups.find(params[:id])
bunding.pry
#@group.group_users.destroy_all
#@group.destroy
redirect_to groups_path , alert:"討論板已刪除"
end
DEVELOPMENT [1] rails101(#<GroupsController>)> @group.group_users.destroy_all
GroupUser Load (0.2ms) SELECT "group_users".* FROM "group_users" WHERE "group_users"."group_id" = ? [["group_id", 58]]
(0.1ms) begin transaction
SQL (0.4ms) DELETE FROM "group_users" WHERE "group_users"."id" = ? [["id", 112]]
(4.1ms) commit transaction
[
[0] #<GroupUser:0x007fc52527ccd8> {
:id => 112,
:group_id => 58,
:user_id => 5,
:created_at => Wed, 09 Mar 2016 16:47:19 UTC +00:00,
:updated_at => Wed, 09 Mar 2016 16:47:19 UTC +00:00
}
]
DEVELOPMENT [2] rails101(#<GroupsController>)> GroupUser.all
GroupUser Load (0.2ms) SELECT "group_users".* FROM "group_users"
[]
這邊可以看得出來GroupUser裡的資料的確都被刪掉了
接下來就換成delete_all
def destroy
@group = current_user.groups.find(params[:id])
bunding.pry
#@group.group_users.delete_all
#@group.destroy
redirect_to groups_path , alert:"討論板已刪除"
end
花惹發~他把我的資料update然後把group_id變成nil,讓這筆資料變成孤兒資料了
DEVELOPMENT [1] rails101(#<GroupsController>)> @group.group_users.delete_all
SQL (4.2ms) UPDATE "group_users" SET "group_id" = NULL WHERE "group_users"."group_id" = ? [["group_id", 59]]
nil
DEVELOPMENT [2] rails101(#<GroupsController>)> GroupUser.all
GroupUser Load (0.2ms) SELECT "group_users".* FROM "group_users"
[
[0] #<GroupUser:0x007fc52d6a1d60> {
:id => 113,
:group_id => nil,
:user_id => 5,
:created_at => Wed, 09 Mar 2016 16:56:36 UTC +00:00,
:updated_at => Wed, 09 Mar 2016 16:56:36 UTC +00:00
}
]
如果要用delete_all刪除資料的話,我自己是試了兩種方法才能用delete_all刪除
第一種是用.all.delete_all
DEVELOPMENT [1] rails101(#<GroupsController>)> @group.group_users.all.delete_all
SQL (4.3ms) DELETE FROM "group_users" WHERE "group_users"."group_id" = ? [["group_id", 60]]
1
第二種就有點脫褲子放屁,不過秉持著try and error的精神還是試了一下,那就是把has_many的dependent: :destroy
加回去跟最上面一樣,然後直接用delete_all就刪的掉了,然後我是先刪group_user的資料才刪group資料的
DEVELOPMENT [1] rails101(#<GroupsController>)> @group.group_users.delete_all
SQL (3.6ms) DELETE FROM "group_users" WHERE "group_users"."group_id" = ? [["group_id", 62]]
nil
DEVELOPMENT [2] rails101(#<GroupsController>)> GroupUser.all
GroupUser Load (0.2ms) SELECT "group_users".* FROM "group_users"
[]
至於為什麼會造成這個bug我還是無解,因為上網查了一下destroy_all跟delete_all的差別,就只是差在一個會呼叫destroy的callback另一個不會,但誰知道delete_all不刪除就算了還給我資料update成孤兒真是一個莫名
我有push到github上了有興趣的人可以來試試看
https://github.com/kurotyan514/rails101.git
我ruby的版本是2.2.2
rails的版本是 4.2.5
後續在這邊
關於delete_all的bug
參考資料
Bruce 的玩具間