Interesting. I felt the use of super/defoverridable not very idiomatic and you feel the same. That was a doubt I had.
The key point is the user of the library. He can create the uploader he wants only adding small pieces of code packaged in plugins. Currently shrine has 43 plugins! The user can as well extend the functionality easily and it can be distributed like a gem.
In my previous example, when the user calls MyUploader.upload(file, {}), the chain is: Plugin::Validation.upload → Plugin::Backup → UploaderBase. Plugins (usually, it may have dependencies) are not aware if other plugins are used. If I use the name of the function I will lose this indirection, I cannot concatenate calls.
I understand and share that OOP can be more complicated than FP in certain scenarios. However, in this one I don’t see it like OOP paradigm, what I interpret is that the author is using the tools the Ruby language gives him to create an environment where composing is easy and cheap — composing in the sense of open-closed principle, entities should be open for extension, but closed for modification — but maybe I’m wrong ![]()
With Elixir I imagine I could do something like:
defmodule Plugin.Backup do
use Plugin.Base
def upload(io, options, next) do
next(io, options)
backup_store(io, options)
end
end
So I’m creating a middleware, but shrine has 4 classes, with 4 or 5 public methods and much more private methods. Plugins modify private methods, as well. I don’t want 100 middlewares.
I don’t want to do OOP with Elixir. I want to achieve the same functionality: the user may choose the plugins for each uploader… but I don’t care exactly how to do it.
@aseigo I really appreciate your time, thank you ![]()






















