we've (rightfully) realized that classes that inherit from complicated structures (like ActiveRecord::Base) creates highly coupled code.

however, moving them into modules and implementing the same complexities with Module#included doesn't really solve the problem.

the problem isn't "include Foo" vs "< Foo". the problem is polluting the class with methods that has all kind of internal data/functionalities.



this code leaves me with so many questions

@judofyr It looks like `Hanami::Action` is prepending a module that overrides `call`. I think that the vast majority of Rubyists would consider this to be unexpected behaviour.


@tom_dalling @judofyr Prepended method behavior is a tricky area. It’s incredibly helpful in some areas but it’s always going to need some explanation to users since it works in the opposite way to the usual inheritance chain.

I agree that this code example produces unexpected results. Modules being included that that should, IMO, add their own API for enhancing methods, or require you to name the methods you want enhanced.

@tom_dalling @judofyr FWIW: In hanami-controller unstable, you now inherit from Hanami::Action instead of including a module. IMO this is a much better design given there is always going to be specific extra behavior added around one method (that being `call`) in order to provide some degree of ergonomics as well as providing/adhering to a particular interface contract.

Inheritance works better here because the class “is an” action versus “also behaves like”, which is better for modules.

@timriley @judofyr If it were me, I'd use two different method names. Probably keep the external interface as `call`, and rename the internal method to `run` or `execute`. Then you don't need prepend, and it's a lot less surprising.

@tom_dalling @timriley @judofyr I solved this in rom-rb like that. See `ROM::Command#call` and `ROM::Command#execute`

Sign in to participate in the conversation

A Mastodon instance for Rubyists & friends