關於delete_all的Bug

在刪除一筆model資料時,如果要連有關聯到的model的資料一起刪除時可以用dependent: :destroy

Group.rb
has_many :group_users , dependent: :destroy

這樣設定的話當group的資料被刪除時,對應到的group_users會跟著一起刪除

因為我自己想要手動來刪除資料所以就用了delete_alldestroy_all,順便試一下兩個method的差別
然後就發現了這個delete_all的bug

要達成這個bug首先要把has_manydependent參數拿掉變成

Group.rb
has_many :group_users 

這邊我先用destroy_all來刪除(實際操作的時候我是先用pry中斷,然後直接在pry的console裡執行刪除的code)

group_controller.rb
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

group_controller.rb
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 的玩具間

comments powered by Disqus