Concern varying for multiple models

Hello everyone,

Recently, I had to introduce a concern that applied to multiple models. But this concern needed some specifics on each of the model where it was applied.

This model was Sizeable, it is a concern I use to compute and retrieve the total size of an object in our application. Objects exists in a variety of forms but their size always end up being the sum of the sizes of their defining ActiveStorage blobs. What changes from model to model is the list of blobs that are responsible for the size computation.

What I ended-up doing is this:

  • one main concern with all common methods used in the size computation or retrieval
  • one sub-concern per model to override the method to list the size-contributing blobs

My problem is about the naming & structure of those files. My main concern should be inside the concerns folder since it apply to many models in my application.

But where should I put the specific sub-concerns for each of my models?

I could put them in a model-specific folder models/thing/sizeable.rb but I don’t like that. It would distance them too much from the main concern they are dependent of. It also would mean that I would have a lot of indistinguishable sizeable.rb files in my application, one for every model.

I could put them in a concern sub-folder models/concerns/sizeable/thing.rb but I don’t like that either. It would mean that I would have a lot of indistinguishable thing.rb files in my application, potentially one for every concern of the model.

I could put them in a concern sub-folder with a specific name models/concerns/sizeable/sizeable_thing.rb. This would solve all my file name problems but that appears a little overkill for a file path.

The solution I ended up doing is models/sizeable/sizeable_thing.rb where I completely discard the concerns folder.


Do you have suggestions for me on a better file structure or concerns organization?

Thanks

I’d consider:

models/concerns/sizeable.rb 
models/concerns/model_name/sizing.rb

Out of curiosity, what’s in a SizeableThing?

If it’s just a method or two, I’d probably be inclined to treat the Sizeable concern like the Ruby Enumerable module — specifically, require any class that includes Sizeable to implement a conventional method (say, sizeable_blobs) which the methods provided by Sizeable depend on.

Alternately, the Sizeable concern could add a class method that allowed it to be configured on a per-model basis (e.g. computes_size_of :blob_a, :blob_c).

I would probably pursue one of those options before solving per-model concerns.

2 Likes

@pvande Yes you got my point. A SizeableThing is a concern to just add the method required for a Thing to be able to include Sizeable, so yeah something like a method sizeable_blobs. But since this method is different for every model I want to use Sizeable on, I need a different implementation for each model.

This specific implementation is what is in SizeableThing. It contains the methods necessary for a Thing to become Sizeable. My problem is that I don’t really know where to store the file for these specific concerns.

My models are already quite big and I am trying to clean them up, so I would rather not add the method directly in the model primary file. Additionally, I would like to keep the SizeableThing as close to Sizeable as possible instead of close to Thing. I feel it is a dependency of the concern and would like to keep the file as close as possible of the concern itself.

Why don’t you delegate the list of sizeable blobs to the model?

include Sizeable
sizeable_blobs only: [:a, :b, :c]