Rails の Dynamic Scopes での delete_all は外部キーを NULL にするだけ

Shop has_many Items という状況のとき、とある shop が持っている items を、下記のように取ることが出来ます。それに対して、条件を設定することも出来ます。

>> @shop.items 
=> [Item id:21 shop_id: 1, Item id: 22, shop_id: 1, ....]
>> @shop.item.find_all_by_category("CPU") 
=> [Item id:23 shop_id: 1, Item id: 26, shop_id: 1, ....]

そこで、同様にとある Shop の Items を全部 delete_all にしようとしたのですが、DELETE されるのではなく、外部キーにNULLがセットされるという挙動になっています。

>> @shop.items.delete_all

とすると

  Item Update (3.0ms)   UPDATE `items` SET shop_id = NULL WHERE (shop_id = 1 AND id IN (22,23,24,25,26)) 

のようになります。

Rails の API を見ると

# File vendor/rails/activerecord/lib/active_record/base.rb, line 897
897:       def delete_all(conditions = nil)
898:         sql = "DELETE FROM #{quoted_table_name} "
899:         add_conditions!(sql, conditions, scope(:find))
900:         connection.delete(sql, "#{name} Delete all")
901:       end

みたいになっているのですが、Dynamic Scopes はまた別のところで定義されているっぽいです。

>> @shop.items.destroy_all

としてみると、下記のように DELETE になりますが、SQL が発行されまくってるのでだめぽいです。そもそも destroy は、destroy をトリガーにしている各種処理をしてから DELETE が行われるので、そもそも delete とは意味合いが違うというので仕方ないです。

Item Destroy (3.0ms)   DELETE FROM `items` WHERE WHERE id = 21
Item Destroy (3.0ms)   DELETE FROM `items` WHERE WHERE id = 22
Item Destroy (3.0ms)   DELETE FROM `items` WHERE WHERE id = 23

ふつうに Item.delete_all を呼ぶかなぁ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です