Inheritance is a common method of reuse in object-oriented software.
Ruby supports single inheritance using subclasses and multiple
inheritance using Mixins. Mixins can be used to package common helpers
or provide a common public interface.
However, mixins have some drawbacks:
They use the same namespace as classes they’re mixed into, which can
cause naming conflicts.
Although they have access to instance variables from classes they’re
mixed into, mixins can’t easily accept initializer arguments, so they
can’t have their own state.
They inflate the number of methods available in a class.
They’re not easy to add and remove at runtime.
They’re difficult to test in isolation, since they can’t be
In our example application, users can invite their friends by email
to take surveys. If an invited email matches an existing user, a private
message will be created. Otherwise, a message is sent to that email
address with a link.
The logic to generate the invitation message is the same regardless
of the delivery mechanism, so this behavior is encapsulated in a
# app/models/inviter.rbmoduleInviterextendActiveSupport::Concern included doincludeAbstractController::RenderingincludeRails.application.routes.url_helpersself.view_paths='app/views'self.default_url_options=ActionMailer::Base.default_url_optionsendprivatedef render_message_body render template: 'invitations/message'endend
Each delivery strategy mixes in Inviter and calls
Although the mixin does a good job of preventing duplicated code, it’s
difficult to test or understand in isolation, it obfuscates the inviter
classes, and it tightly couples the inviter classes to a particular
message body implementation.