ActiveRecord - получить последние n записей и удалить их в одной команде?
Привет всем и спасибо за то, что нашли время, чтобы ответить на мой вопрос.
Вопрос действительно объясняется в заголовке.
Я попробовал Model.last(n).destroy_all, но ничего из этого не получилось.
Мне было интересно, можно ли сделать это в одной строке, а если нет, то какой будет самый чистый способ сделать это?
Еще раз спасибо!
Ответы
Ответ 1
это удалит последние n записей в одном запросе sql
Model.order('created_at DESC').limit(n).destroy_all
UPDATE:
Более эффективным способом будет:
ids = Model.order('created_at DESC').limit(n).pluck(:id)
Model.where(id: ids).delete_all
Хотя это не одна команда, она выполняет только 2 SQL-запроса
Ответ 2
Вы можете достичь этого:
Model.last(n).each(&:destroy)
@ИванДенисов указывает еще один способ сделать это:
Model.order('created_at DESC').limit(n).destroy_all
В основном он делает то же самое в соответствии с Rails API Doc, но немного подробный. Кроме того, он не делает все в одном запросе SQL.
Подробное сравнение SQL-запросов
Я попытался запустить оба кода в rails console
под Ruby 2.0.0p253 && & Rails 4.0.4, вот результаты:
2.0.0p353 :002 > Role.last(3).each(&:destroy)
Role Load (1.0ms) SELECT "roles".* FROM "roles" ORDER BY "roles"."id" DESC LIMIT 3
(0.3ms) BEGIN
SQL (3.5ms) DELETE FROM "roles" WHERE "roles"."id" = $1 [["id", 5487]]
(11.8ms) COMMIT
(0.1ms) BEGIN
SQL (0.2ms) DELETE FROM "roles" WHERE "roles"."id" = $1 [["id", 5488]]
(5.4ms) COMMIT
(0.1ms) BEGIN
SQL (0.2ms) DELETE FROM "roles" WHERE "roles"."id" = $1 [["id", 5489]]
(4.6ms) COMMIT
2.0.0p353 :004 > Role.order('created_at DESC').limit(3).destroy_all
Role Load (0.9ms) SELECT "roles".* FROM "roles" ORDER BY created_at DESC LIMIT 3
(0.2ms) BEGIN
SQL (0.2ms) DELETE FROM "roles" WHERE "roles"."id" = $1 [["id", 5492]]
(6.6ms) COMMIT
(0.2ms) BEGIN
SQL (0.2ms) DELETE FROM "roles" WHERE "roles"."id" = $1 [["id", 5491]]
(0.4ms) COMMIT
(0.1ms) BEGIN
SQL (0.1ms) DELETE FROM "roles" WHERE "roles"."id" = $1 [["id", 5490]]
(0.2ms) COMMIT
Части DELETE
точно такие же. Они оба выполнили несколько SQL-запросов.
Единственное отличие - это SELECT
part, если мы изменим 'created_at DESC'
на 'id DESC'
, они будут точно такими же.