回答:
基本的にdestroy
は、モデルに対してコールバックを実行しますが、実行しdelete
ません。
Rails APIから:
ActiveRecord::Persistence.delete
データベース内のレコードを削除し、このインスタンスをフリーズして、変更を加える必要がないことを反映します(永続化できないため)。凍結されたインスタンスを返します。
行は、レコードの主キーに対するSQL DELETEステートメントで単純に削除され、コールバックは実行されません。
オブジェクトのbefore_destroyおよびafter_destroyコールバック、または:dependentアソシエーションオプションを適用するには、#destroyを使用します。
ActiveRecord::Persistence.destroy
データベース内のレコードを削除し、このインスタンスをフリーズして、変更を加える必要がないことを反映します(永続化できないため)。
destroyに関連する一連のコールバックがあります。before_destroyコールバックがfalseを返す場合、アクションはキャンセルされ、destroyはfalseを返します。詳細については、ActiveRecord :: Callbacksを参照してください。
model#before_destroy
最終的なdestroy()
呼び出しを停止するために使用できるコールバックです。
delete
dbから現在のオブジェクトレコードを削除するだけで、関連する子レコードはdbから削除しません。
destroy
現在のオブジェクトレコードをdbから削除し、関連する子レコードもdbから削除します。
それらの使用は本当に重要です:
複数の親オブジェクトが共通の子オブジェクトを共有している場合、destroy
特定の親オブジェクトを呼び出すと、他の複数の親の間で共有されている子オブジェクトが削除されます。
destroy
ある子孫ではなく、子供のドキュメントによると、破壊する「属性から新しいオブジェクトを作成し、それを破壊する呼び出します。」:rubydoc.info/docs/rails/4.1.7/ActiveRecord%2FRelation:destroy
はい、2つの方法には大きな違いがあります。モデルコールバックを呼び出さずにレコードをすばやく削除する場合は、delete_allを使用します。
モデルのコールバックを気にする場合は、destroy_allを使用してください。
公式ドキュメントから
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class
destroy_all(conditions = nil)public
各レコードをインスタンス化してdestroyメソッドを呼び出すことにより、条件に一致するレコードを破棄します。各オブジェクトのコールバックが実行されます(:依存関係オプションとbefore_destroy / after_destroy Observerメソッドを含む)。破棄されたオブジェクトのコレクションを返します。(永続化できないため)変更を加えてはならないことを反映して、それぞれがフリーズされます。
注:一度に多くのレコードを削除する場合、インスタンス化、コールバックの実行、および各レコードの削除には時間がかかる場合があります。レコードごとに少なくとも1つのSQL DELETEクエリを生成します(コールバックを強制するために、場合によってはそれ以上)。関連付けやコールバックを考慮せずに多数の行をすばやく削除する場合は、代わりにdelete_allを使用します。
基本的に「削除」は、クエリをデータベースに直接送信して、レコードを削除します。その場合、Railsは、削除するレコードにどの属性があるのか、またはコールバック(before_destroy
)。
"destroy"メソッドは渡されたIDを取得し、 "find"メソッドを使用してデータベースからモデルをフェッチしてから、それに対してdestroyを呼び出します。つまり、コールバックがトリガーされます。
コールバックがトリガーされないようにする場合、またはパフォーマンスを向上させる場合は、「削除」を使用します。それ以外の場合(およびほとんどの場合)、「破棄」を使用する必要があります。
すでに多くの答えがあります。もう少しジャンプしたかった。
docs:
has_manyの場合、destroyおよびdestroy_allは常に、削除されるレコードのdestroyメソッドを呼び出し、コールバックが実行されるようにします。ただし、deleteとdelete_allは、:dependentオプションで指定された方法に従って削除を行うか、:dependentオプションが指定されていない場合は、デフォルトの方法に従います。デフォルトの戦略は何もしないことです(外部キーは親IDを設定したままにします)。ただし、has_many:throughを除き、デフォルトの戦略はdelete_all(コールバックを実行せずに結合レコードを削除)です。
delete
verbageはのために動作が異なりますActiveRecord::Association.has_many
とActiveRecord::Base
。後者の場合、deleteが実行されSQL DELETE
、すべての検証/コールバックがバイパスされます。前者は:dependent
、関連付けに渡されたオプションに基づいて実行されます。しかし、テスト中に、コールバックが実行されるだけdelete
でなくdelete_all
dependent: :destroy
例:
class Parent < ApplicationRecord
has_many :children,
before_remove: -> (_) { puts "before_remove callback" },
dependent: :destroy
end
class Child < ApplicationRecord
belongs_to :parent
before_destroy -> { puts "before_destroy callback" }
end
> child.delete # Ran without callbacks
Child Destroy (99.6ms) DELETE FROM "children" WHERE "children"."id" = $1 [["id", 21]]
> parent.children.delete(other_child) # Ran with callbacks
before_remove callback
before_destroy callback
Child Destroy (0.4ms) DELETE FROM "children" WHERE "children"."id" = $1 [["id", 22]]
> parent.children.delete_all # Ran without callbacks
Child Destroy (1.0ms) DELETE FROM "children" WHERE "children"."parent_id" = $1 [["parent_id", 1]]