How would I destroy_all or delete_all records except one in ruby on rails?

I would consider a slightly different approach and have the model that has the has_many relationship have :dependent => destroy with it, e.g.
User has_many :messages, :dependent => :destroy That way you don't get the 'dangling orphan record' issue you describe.

I would try and approach it this way rather than thinking 'all records except'.
I don't know if there is something I am not addressing but this is what comes to find for the issue described.


Nowadays in Rails 4, you can do:

Model.where.not(attr: "something").delete_all

and

Model.where.not(attr: "something").destroy_all

And don't forget about difference:

  • destroy_all: The associated objects are destroyed alongside this object by calling their destroy method. Instantiates all the records and destroys them one at a time, so with a large dataset, this could be slow
  • delete_all: All associated objects are destroyed immediately without calling their destroy method. Callbacks are not called.

This worked for me in the end.

Message.where('id != ? AND parent_id = ?', parent_id, parent_id).where(:sender_status => 1, :recipient_status => 1).delete_all

Basically returns all messages of that particular conversation except the one where id == parent_id. Whenever id == parent_id this means it's a parent message.


Why not use association from the parent record, something like this?

Message.where(:id => parent_id).first
  .children.where(:sender_status => 1, :recipient_status => 1)
  .delete_all