I talked about the “nomenlature knot” in the last post but after trying to write about it a few times, I came to realize this topic has more rabbit holes than Watership Down. So, I’m deferring my post(s) and maybe starting a new series on it. Since I would rather move forward with the next posts in this series, lets go on with variations on delete actions.

Lots of applications complicate or even replace the action of deleting resources but preserve for the user the notional interface of deletion. There’s many good reasons for this–mainly to smooth recovery from accidents with an “undoable” delete. I usually hear this called a “soft delete”. Lets examine a “soft delete” feature, discuss what makes this different from a “hide” feature, and the setup for a “hard delete” which actually deletes something.

Here’s a feature description for “soft delete”

Given a user visiting the view for Wat
When the user clicks on the delete button to submit the Wat delete request
Then the Wat property "deleted_at" is updated with the current datetime
And the user redirected to Wat index view
And the "deleted" Wat is not shown on the index
And the user is presented with an alert informing that the Wat resource was deleted

This is the same feature we might write for a normal delete but instead of deleting the feature we are updating a property of the resource: in our example, deleted_at is updated with a current datetime.

This feature description could be fairly criticized as being too bound up in the implementation details of the model for a proper “behavior driven development” feature definition. But the effects have to be specified somewhere and the justification for that implementation also. For this discussion, we have to know that instead of deleting a record in a DB, we’re updating a property of that record.

We’ll examing two options for implementing it:

  • change the “delete” button to send a hidden form updating the deleted_at
  • change the WatsController#delete action to update Wat#deleted_at instead

Let’s go.

Delete button sends update request

ClientClientWatsController#updateWatsController#updatePATCH /wats/{wat_id}deleted_at={current_datetime_utc}update wat303 See OtherLocation: /index

What’s nice about this implentation is that, the pretense of deletion is implemented by client labeling, and the API action is “normal” even though it’s not what the user interface says is happening. This implementation is most amenable if the “deleted” resources are exposable and manageable by users, in which case, maybe the semantics of the whole feature should be reconsidered. Perhaps instead of “delete” and “undelete” the actions should be labeled with “hide” and “show” or “remove” and “restore” or something like that.

This sort of “conceal/reveal” semantics should probably be reflected in the model, which may mean rewriting the feature description. There could be different kinds perhaps implemented different ways for different properties. That’ll have to be discussed in a different post though. For this post, allow, that, if we’re not updated a property called deleted_at, we could just as easily be updating a property with more semantically appropriate name.

Delete action updates property

ClientClientWatsController#deleteWatsController#deleteDELETE /wats/{wat_id}update wat deleted_at current_datetime_utc303 See OtherLocation: /index

Here the server owns the feature, and client’s actions are co-opted to implement the “soft delete”. This is good if the feature should be hidden from the users and clients. However if so, we require other sorts of management features for dealing with the “deleted” features.

Summary and conclusion

The soft delete works through filtering–the index view automatically excludes the deletion property we called deleted_at. Some questions to ask are:

  • When is exposing the deletion property to the client desirable?
  • How can users see a list of “deleted” resources?
  • How can users reverse or “undelete” deleted resources?
  • How can a resource be “hard deleted”?
    • automatic “garbage collection” process
    • administrative delete action
  • How can “lifecycle” changes like this be logged, reported on, or audited?
  • What/How are associated resources effected by this kind of “delete”? (grateful thanks to the reader who suggested this)

If soft deleted resources are managable by users, I think it’s worth considering whether the semantics should be shifted to a “hide/show” sort of labelling. The property to be updated would be changed, and the controls labeled for concealing and revealing resources.

This feature’s dependency on what I’m just going to call “application semantics” really stands out to me in a way that didn’t with the copy features. I’m planning to write about “conceal/reveal” features soon-if-not-next. But I’m going to have to come up with a way to talk oabout this “application semantics” thing also.