Enforces "waterfall" method ordering: define methods after any method that calls them within the same scope.
- RuboCop::SortedMethodsByCall
- Waterfall ordering enforcement: Caller methods must be defined before their callees;
- Smart visibility handling: Respects
private/protected/publicsections; - Safe mutual recursion: Handles recursive method calls gracefully;
- Autocorrection support: Automatically reorders methods (opt-in with
-A); - Full RuboCop integration: Works seamlessly with modern RuboCop plugin system;
- Comprehensive scope support: Classes, modules, singleton classes, and top-level;
Add this line to your application's Gemfile:
gem 'rubocop-sorted_methods_by_call'And then execute:
bundle installOr install it yourself:
gem install rubocop-sorted_methods_by_callAdd to your .rubocop.yml:
plugins:
- rubocop-sorted_methods_by_call
SortedMethodsByCall/Waterfall:
Enabled: trueSortedMethodsByCall/Waterfall:
Enabled: true
SafeAutoCorrect: false # Autocorrection requires -A flag
AllowedRecursion: true # Allow mutual recursion (default: true)
# If true, the cop will NOT add "called together" sibling-order edges
# that would introduce a cycle with existing constraints. This reduces
# impossible-to-fix sibling offenses and makes autocorrect more reliable.
#
# Default: false
SkipCyclicSiblingEdges: falseIn waterfall ordering, callers come before callees. This creates a top-down reading flow where main logic appears before implementation details.
class Service
def call
foo
bar
end
private
def bar
method123
end
def method123
foo
end
def foo
123
end
endclass Service
def call
foo
bar
end
private
def foo # ❌ Offense: Define #foo after its caller #method123
123
end
def bar
method123
end
def method123
foo
end
endSortedMethodsByCall/Waterfall enforces two kinds of ordering constraints:
- Direct call edges: if
callercallscallee, thencallermust be defined beforecallee. - Sibling ("called together") edges: in orchestration methods (methods not called by others in the same scope),
consecutive calls imply an intended order (e.g.,
athenb), soashould be defined beforeb.
Sometimes these constraints can conflict and create a cycle, which means there is no valid ordering that satisfies all constraints. In this situation, autocorrect may be skipped.
Example:
class SiblingCycleExample
def call
a
b
end
private
def b
c
end
def c
a
end
def a; end
endHere, the direct dependencies imply b -> c -> a, but the orchestration method implies a -> b,
which forms the cycle a -> b -> c -> a.
If you prefer to keep the warning (to encourage refactoring), leave SkipCyclicSiblingEdges: false.
If you prefer the cop to avoid enforcing sibling edges that create cycles, set SkipCyclicSiblingEdges: true.
Run with unsafe autocorrection to automatically fix violations:
bundle exec rubocop -AThis will reorder the methods while preserving comments and visibility modifiers.
Run the test suite:
bundle exec rspecRun RuboCop on the gem itself:
bundle exec rubocop
bundle exec rubocop --config test_project/.rubocop.test.yml lib/ -AAfter checking out the repo, run:
bin/setupThis will install dependencies and start an interactive console.
bin/console- Interactive development consolebin/setup- Install dependencies and build gembundle exec rake- Run tests and linting
- Update version in
lib/rubocop/sorted_methods_by_call/version.rb - Create and push a git tag:
git tag v0.1.0 && git push origin v0.1.0 - GitHub Actions will automatically:
- Build the gem
- Publish to RubyGems.org
- Create a GitHub release
- Ruby: >= 2.7
- RuboCop: >= 1.72.0 (required for plugin system)
Bug reports and pull requests are welcome! Please follow these guidelines:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -am 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a pull request
Please ensure your code passes all tests and follows the existing style.
Code is covered with YARD docs, you can access online docs at https://unurgunite.github.io/rubocop-sorted_methods_by_call_docs/
The gem is available as open source under the terms of MIT License.
Everyone interacting with this project is expected to follow the Code of Conduct.
Note: This gem implements true waterfall ordering that considers the complete call graph across all methods in a scope. Methods are ordered so that every callee appears after all of its callers, creating a natural top-down reading flow.