Hello all and thanks for taking the time to answer my question.
The question is really explained in the title.
I tried Model.last(n).destroy_all but none of that would work.
I was wondering if it is possible to do it in one line, and if not what would be the cleanest way of doing it?
Thanks again!
Active Record allows you to validate the state of a model before it gets written into the database. There are several methods that you can use to check your models and validate that an attribute value is not empty, is unique and not already in the database, follows a specific format, and many more.
ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.
Rails delete operation using destroy method By using destroy, you can delete the record from rails as well as its other existing dependencies. So in the context of our rails application, if we delete a book record using the destroy function, the authors associated with the book will also be deleted.
ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code.
To do it in one SQL query use delete_all
:
Model.order(created_at: :desc).limit(n).delete_all
But delete_all
won't execute any model callbacks or validations
To run callbacks and validations use destroy_all
:
Model.order(created_at: :desc).limit(n).destroy_all
Unfortunately destroy_all
will execute n + 1 SQL queries: 1 query to retrieve records and n queries to delete each record.
You can achieve this by:
Model.last(n).each(&:destroy)
@IvanDenisov points out another way to do this:
Model.order('created_at DESC').limit(n).destroy_all
It's basically doing the same thing according to Rails API Doc, but a little bit verbose. Besides, it doesn't do all things in one SQL query.
Detailed comparison of SQL queries
I tried to run both codes in rails console
under Ruby 2.0.0p253 && Rails 4.0.4, here are the results:
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
The DELETE
parts are exactly the same. They both took multiple SQL queries.
The only difference is SELECT
part, if we change 'created_at DESC'
to 'id DESC'
, they will be exactly the same too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With