Hi, I was very surprised by difference of delete_all on association vs model(delegated to relation). Given TaskFilter.has_many(:qualifiers, :class_name=>‘TaskFilterQualifier’)
TaskFilter.delete_all => one DELETE statement
Without :dependent option on “qualifiers” association
TaskFilter.first.qualifiers.delete_all =>
SELECT task_filter_qualifiers
.* FROM task_filter_qualifiers
WHERE (task_filter_qualifiers
.task_filter_id = 1)
BEGIN
UPDATE task_filter_qualifiers
SET task_filter_id
= NULL WHERE task_filter_qualifiers
.task_filter_id
= 1 AND task_filter_qualifiers
.id
IN (90, 91)
COMMIT
Why UPDATE, not DELETE ?
With :dependent => :destroy TaskFilter.first.qualifiers.delete_all =>
TaskFilter Load (0.9ms) SELECT task_filters
.* FROM task_filters
LIMIT 1
TaskFilterQualifier Load (0.9ms) SELECT task_filter_qualifiers
.* FROM task_filter_qualifiers
WHERE (task_filter_qualifiers
.task_filter_id = 1)
SQL (0.2ms) BEGIN
AREL (6.6ms) DELETE FROM task_filter_qualifiers
WHERE (task_filter_qualifiers
.id
= 92)
TaskFilter Load (6.4ms) SELECT task_filters
.* FROM task_filters
WHERE (task_filters
.id
= 1) LIMIT 1
AREL (0.6ms) UPDATE task_filters
SET updated_at
= ‘2010-11-24 09:28:03’ WHERE (task_filters
.id
= 1)
AREL (2.6ms) DELETE FROM task_filter_qualifiers
WHERE (task_filter_qualifiers
.id
= 93)
TaskFilter Load (8.2ms) SELECT task_filters
.* FROM task_filters
WHERE (task_filters
.id
= 1) LIMIT 1
AREL (1.7ms) UPDATE task_filters
SET updated_at
= ‘2010-11-24 09:28:03’ WHERE (task_filters
.id
= 1)
SQL (53.5ms) COMMIT
Note that I have :touch option, so sql below is produced by :touch callback
TaskFilter Load (6.4ms) SELECT task_filters
.* FROM task_filters
WHERE (task_filters
.id
= 1) LIMIT 1
AREL (0.6ms) UPDATE task_filters
SET updated_at
= ‘2010-11-24 09:28:03’ WHERE (task_filters
.id
= 1)
That is nightmare, I expect delete_all to be fast sql query, but instead I have:
- all associated objects loaded
- each object was destroyed, with many callbacks and DELETE queries
delete_all, clear, destroy_all respect :dependent option, but why ? If association hasn’t :dependent option, then delete_all is duplicate of clear if association has :dependent=> :destroy option, then delete_all, clear are duplicates of destroy_all
delete_all work fine on relation so, TaskFilter.first.qualifiers.scoped.delete_all will work fine:
TaskFilter Load (1.3ms) SELECT task_filters
.* FROM task_filters
LIMIT 1
AREL (71.7ms) DELETE FROM task_filter_qualifiers
WHERE (task_filter_qualifiers
.task_filter_id = 1)
Is this all intentional behavior ?
Maybe this ticket is related https://rails.lighthouseapp.com/projects/8994/tickets/5196-delete_allnullify-in-associations-does-uneeded-queries
Thanks, Anatoliy Lysenko