Skip to content

Instantly share code, notes, and snippets.

@keithrbennett
Created September 19, 2022 14:34
Show Gist options
  • Save keithrbennett/5b1c40dcdff34dbbc242cb0208f8ef7e to your computer and use it in GitHub Desktop.
Save keithrbennett/5b1c40dcdff34dbbc242cb0208f8ef7e to your computer and use it in GitHub Desktop.
# Any module (not class) that includes SemanticLogger::Loggable must also implement an
# `included` method that gets the including class to also include SemanticLogger::Loggable.
# This is because the module's instance method `logger`, when it becomes part of the including
# class, will look for `self.class.logger` when called, and `self` will evaluate to the instance
# of the class and not the module. Having the class include `Loggable` will cause a class method
# `logger` to be created so that this will work.
#
# This method returns the modules that have included Loggable but do not have an `included`
# method implementation. This is an imperfect test since we are not testing the content of that
# implementation, but I don't know a better way.
#
# Since we are asking ObjectSpace for the modules, we are assuming that all modules we need
# to test have already been loaded. I think this is a reasonable assumption.
specify 'must force class that include modules using SemanticLogger to include Loggable' do
suspicious_modules = ObjectSpace.each_object(Module).select do |object|
# All Class'es are modules, but we are not interested in them, so we exclude them.
!object.is_a?(Class) \
&& \
object.ancestors.include?(SemanticLogger::Loggable) \
&& \
!object.respond_to?(:included) \
&& \
(!object.equal?(SemanticLogger::Loggable))
end
expect(suspicious_modules.map(&:name).sort.join("\n")).to eq('')
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment