2011-07-14 6 views
150

私はテーブルからレコードを削除する最良の方法を探しています。たとえば、ユーザーIDが多数の表にまたがるユーザーがあります。このユーザーと、すべてのテーブルでIDを持つすべてのレコードを削除します。delete_allとdestroy_all?

u = User.find_by_name('JohnBoy') 
u.usage_indexes.destroy_all 
u.sources.destroy_all 
u.user_stats.destroy_all 
u.delete 

これは動作し、すべてのテーブルからユーザーのすべての参照を削除しますが、私はdestroy_allは非常にプロセス重かったことを聞いたので、私はdelete_allを試してみました。自分のユーザーテーブルからユーザーを削除するだけで、他のすべてのテーブルのidはnullになりますが、レコードはそのまま残ります。このようなタスクを実行するために正しいプロセスが何かを共有することはできますか?

私は、destroy_allがすべての関連オブジェクトでdestroy関数を呼び出していることを確認していますが、正しいアプローチを確認したいだけです。

答えて

187

あなたは正しいです。 Rails :dependent => :destroy VS :dependent => :delete_all

  • destroy: - あなただけのユーザーを削除したい場合は、関連するすべてのオブジェクト抑制することなく、しかし>destroy_all - >delete_all

    この記事によると、あなたは、ユーザーおよび関連するすべてのオブジェクトを削除する場合/ destroy_all:関連オブジェクトはdestroyメソッドを呼び出すことによってこのオブジェクトと一緒に破棄されます

  • delete/delete_all:関連するすべてのオブジェクトは、destroyメソッド
+61

また、1)コールバックは 'delete_all'を使用してもコールされず、2)' destroy_all'はすべてのレコードをインスタンス化し、一度に1つずつ破棄するので、非常に大きなデータセットでは痛いほど遅くなる。 –

+0

モデルでbefore_destroyメソッドを実行しているとします。もしdelete_allを使用すると、このメソッドは実行されません。第二に、私は私のモデルでbefore_deleteメソッドを使用する場合、これはレールのコンソールでdeleteまたはdelete_allを実行すると実行されますか? – BKSpurgeon

19

delete_allは、単一のSQL DELETE文です。 destroy_allは少なくとも:NUM_OF_RESULTS個のSQL文である可能性のある条件(もしあれば)のすべての一致する結果に対してdestroy()を呼び出します。

大規模なデータセットでdestroy_all()などの劇的な処理が必要な場合は、おそらくアプリケーションから処理して手動で注意して処理することになります。データセットが十分に小さい場合、それほど傷つくことはありません。

16

destroy_allは、すべてのレコードをインスタンス化して一度に1つずつ破棄しないように、モデルクラスから直接使用できます。

ので、代わりの:

u = User.find_by_name('JohnBoy') 
u.usage_indexes.destroy_all 

あなたが行うことができます。結果は、すべての関連レコード

+0

関連するレコードのdestroyコールバックを呼び出すか、 'UsageIntex.delete_all'と同等の' UsageIndex.destroy_all'ですか? – Magne

1

を破壊する1つのクエリです

u = User.find_by_name('JohnBoy') 
UsageIndex.destroy_all "user_id = #{u.id}" 

私が軽減することができsmall gemを作りましたいくつかの状況で関連するレコードを手動で削除する必要があります。依存

この宝石は、ActiveRecordのアソシエーションの新しいオプションが追加されていますdelete_recursively

レコードを破壊する

は、このオプションを使用して関連付けられているすべてのレコードが再帰的に削除されます(つまり、モデル間で)、それらのいずれかをインスタンス化せずに。

depend::deleteまたはdependent::delete_allと同様に、この新しいオプションは依存レコードのaround/before/after_destroyコールバックをトリガーしません。

しかし、依存関係::delete_recursivelyに関連付けられているモデルのチェーン内の任意の場所にdependent::destroy関連付けを持たせることは可能です。 :destroyオプションは、行の上または下のどこでも正常に動作し、すべての関連レコードをインスタンス化して破棄し、コールバックをトリガします。

+0

これは素晴らしいです!私はもっ​​と多くの人々がギターでそれを見たり、主演したりフォークしたりしたのはなぜだろうか。 – Magne

+0

@Magneありがとう!それは機能しているはずです。テストは、Ruby 2.4.1とRails 5.1.1で実行されます。これまで私は個人的にしか使用していませんでしたが、主要なバージョンでは "0"なので、大きな問題ではありませんでした。それはかなりシンプルなので、うまくいくはずです。 – Janosch

+0

クール。私はRuby 2.3.1と 'rails'、 '〜> 4.1.14'でプロジェクトを実行していますが、悲しいことに、他の宝石のためにactiverecord(〜4.1.0)に頼ってしまいました。 delete_recursivelyが0.9.0に解決されていることがわかります。 activerecord 4.1で動作する古いバージョンはありますか?私はgithubのリリースタブには何も見つかりませんでした。 – Magne

関連する問題