Concerns, object orientedness, and type checks – implementing soft delete

Hi there, I"m working with a colleague on a pretty simple idea and wanted to get some feedback on The Rails Way (and to some extent the Ruby Way) to implement this.

Basic idea is that we’ve implemented a Deletable module or model concern for handling soft deletes for some objects (yes, I know there are some existing gems out there acts_as_paranoid).

We’re trying to decide how best to handle a visibility check that basically does the following:

def visible? (record)
  record && record.not_deleted?

but obviously only if record is Deletable. If it’s not, we’re thinking some kind of default implementation for all objects that are not Deletable that just returns true.

What is the consensus or some considerations on doing explicit type checks such as:

 asset.class.include?(Deletable) && asset.deleted

vs implementing something in the hierarchy itself where Deletable models respond one way and others another. Advantage of the former is that things that are not Deletable don’t have to have some way to tell a caller that they’re not deletable so they’re none the wiser. That said, something about that feels like a type check that ought be embedded in the object hierarchy itself.

If we were to pursue the latter, is there a particular pattern that mimics an abstract class in something like Java where we can be sure all future models we implement respond in some sensible way?

So main questions are:

  • How to handle the differentiation of Deletable vs non-deletable models?
  • Where might something like that utility method live? I thought about putting it on the models themselves initially but it can’t do its own nil check so I thought perhaps a class method on ApplicationRecord or something: File.visible? (file)

Would love some thoughts on this from the community.