Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: How to prevent the deletion of records?

I have a model Country and therefore a table countries. The countries table act as a collection of iso country and currency codes and should never reduce there content (after I have filled it with seed data). Because Country is a subclass of ActiveRecord::Base it inherits class methods like destroy, delete_all and so forth which deletes records. I'm looking for a solution to prevent the deletion of records at the model level.

Ofc. I know that I can make use of the object oriented approach to solve this problem by overriding this methods (and raise for instance an error when they called), but this assumes that I have to know all the inherited methods of the base class. I would be glad if someone could offer a more elegant solution.

like image 940
BobMcgregor Avatar asked Sep 01 '16 20:09

BobMcgregor


1 Answers

Taking inspiration from Mark Swardstrom answer, I propose the following that is working also on Rails > 5.0:

Within your model:

before_destroy :stop_destroy

def stop_destroy
  errors.add(:base, :undestroyable)
  throw :abort
end

The following will make all calls to model.destroy return false and your model will not be deleted.

You can argue that still, calls to model.delete will work, and delete your record, but since these are lower level calls this makes perfectly sense to me.

You could also delete the records directly from the database if you want, but the above solution prevents deletion from the application level, which is the right place to check that.

Rubocop checks your calls to delete or delete_all and raises a warning, so you can be 100% sure that if you call model.delete is because you really want it.

My solution works on latest Rails versions where you need to throw :abort instead of returning false.

like image 74
coorasse Avatar answered Oct 10 '22 17:10

coorasse