ActiveRecord - 获取最后n条记录并在一个命令中删除它们?

Dra*_*gan 15 ruby rails-activerecord

大家好,感谢您抽出宝贵时间回答我的问题.

问题在标题中得到了解释.

我尝试过Model.last(n).destroy_all,但这些都没有用.

我想知道是否可以在一行中完成它,如果不是最干净的方法呢?

再次感谢!

Iva*_*sov 35

这将删除一个SQL查询中的最后n条记录

Model.order('created_at DESC').limit(n).destroy_all
Run Code Online (Sandbox Code Playgroud)

更新:更有效的方式是:

ids = Model.order('created_at DESC').limit(n).pluck(:id)
Model.where(id: ids).delete_all
Run Code Online (Sandbox Code Playgroud)

虽然它不是一个命令,但它只执行2个SQL查询

  • 不,这不是一个SQL查询.我在Ruby 2.0.0p253 && Rails 4.0.2上试过这个,结果如下:https://gist.github.com/pinepara/8433912 @Dragan (2认同)
  • @IvanDenisov你的意思是使用`delete_all`而不是`destroy_all`?讨厌这样说但不会再说.`delete_all`不支持限制范围. (2认同)

Jun*_*hou 8

你可以通过以下方式实现:

Model.last(n).each(&:destroy)

@IvanDenisov指出了另一种方法:

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
Run Code Online (Sandbox Code Playgroud)

DELETE部分是完全一样的.他们都进行了多次SQL查询.

唯一的区别是SELECT一部分,如果我们换'created_at DESC''id DESC',他们将完全一样了.