rubocop-style-compact_nesting
A RuboCop plugin that enforces a hybrid module/class nesting style:
- All namespace segments are collapsed onto a single
moduleline using::. - When the innermost definition in a wrapper chain is a
class, that class is nested separately inside the compactmodulewrapper. - When the chain is entirely modules, every segment is collapsed into a
single compact
module A::B::Cwrapping the body directly.
Canonical form
module A::B::C
class D
# ...
end
end
Examples
# bad
module A
module B
class C
# ...
end
end
end
# good
module A::B
class C
# ...
end
end
# bad
class A::B::C
# ...
end
# good
module A::B
class C
# ...
end
end
# good (no namespace)
class Foo
# ...
end
# bad
module A
module B
module C
end
end
end
# good (module-only chain collapses to one compact module)
module A::B::C
end
Installation
# Gemfile
gem 'rubocop-style-compact_nesting', require: false
# .rubocop.yml
plugins:
- rubocop-style-compact_nesting
The plugin disables Style/ClassAndModuleChildren by default because that
cop enforces the opposite layout. If you want it back, re-enable it in
your own config:
Style/ClassAndModuleChildren:
Enabled: true
Requires RuboCop >= 1.72 and Ruby >= 3.1.
Rules
Style/CompactModuleNesting
- Detects chains of wrapper modules whose body is a single nested
module/class ending in a
class, and rewrites them to one compact outermodule A::B::Cwith a separately nested innermostclass D. - Rewrites
class A::B::Ctomodule A::B; class C; end; end. - Collapses pure module-only chains into a single compact
module A::B::Cwrapping the body directly. - Flags (without autocorrect) files that define more than one top-level module/class.
- Ignores bare top-level classes/modules with no namespace.
- Ignores wrapper modules whose body contains anything besides a single nested definition (e.g. constants, methods, or sibling classes).
License
MIT