Overview
RuboCop is a Ruby static code analyzer and formatter based on the Ruby Style Guide. It examines Ruby code and reports violations of style guidelines, potential bugs, and code smells while providing automatic correction capabilities for many issues.
RuboCop operates through a collection of cops (analyzers) organized into departments like Layout, Style, Lint, Metrics, and Naming. Each cop checks for specific patterns and can suggest or automatically apply corrections. The tool integrates with editors, CI systems, and development workflows to maintain code quality across Ruby projects.
The main classes include RuboCop::CLI
for command-line operations, RuboCop::Runner
for executing cops, and RuboCop::Cop::Base
as the foundation for all analysis rules. Configuration happens through .rubocop.yml
files that define which cops to enable, their severity levels, and customization options.
# Basic RuboCop violation
def bad_method( x,y )
return x+y
end
# RuboCop-compliant version
def good_method(first, second)
first + second
end
RuboCop supports multiple output formats including JSON, JUnit XML, and human-readable text. The auto-correction feature can fix many violations automatically, while others require manual intervention based on the cop's design and safety considerations.
# Running RuboCop programmatically
require 'rubocop'
cli = RuboCop::CLI.new
result = cli.run(['--format', 'json', 'app/'])
# Returns exit code: 0 for success, 1 for violations found
Basic Usage
Install RuboCop through gem installation and run it against Ruby files or directories. The basic command analyzes code and reports violations with file locations, line numbers, and descriptions of issues found.
# Gemfile
gem 'rubocop', require: false
# Command line usage
bundle exec rubocop
bundle exec rubocop app/models/
bundle exec rubocop --auto-correct app/controllers/users_controller.rb
The --auto-correct
flag applies safe corrections automatically, while --auto-correct-all
includes potentially unsafe corrections. Use --safe-auto-correct
to apply only corrections marked as safe by cop authors.
# Example violations RuboCop detects
class UserService
def initialize(user)
@user=user # Style/SpaceAroundOperators
end
def process() # Style/DefWithParentheses
if @user.nil? # Style/GuardClause
return false
end
@user.update(status: 'active')
return true # Style/RedundantReturn
end
end
Configuration files control RuboCop behavior through .rubocop.yml
placed in project root or parent directories. RuboCop searches upward through the directory tree until it finds configuration files, merging settings hierarchically.
# .rubocop.yml
AllCops:
TargetRubyVersion: 3.0
NewCops: enable
Exclude:
- 'vendor/**/*'
- 'db/schema.rb'
Style/Documentation:
Enabled: false
Metrics/LineLength:
Max: 120
Individual cops accept configuration parameters that modify their behavior. Common parameters include Max
for metric cops, Enabled
for turning cops on/off, and cop-specific options that change detection patterns.
# Running specific cops or departments
bundle exec rubocop --only Style/TrailingCommaInHashLiteral
bundle exec rubocop --except Lint/UnusedMethodArgument
bundle exec rubocop --only Style,Layout
The --display-cop-names
flag shows which cop triggered each offense, helping identify patterns and configure suppressions. Use --display-only-fail-level-offenses
to see only violations that would cause RuboCop to exit with a failure status.
Advanced Usage
Custom cop development allows teams to enforce project-specific rules beyond RuboCop's built-in cops. Create custom cops by inheriting from RuboCop::Cop::Base
and implementing node pattern matching for Abstract Syntax Tree analysis.
# lib/custom_cops/no_sleep_cop.rb
module CustomCops
class NoSleepCop < RuboCop::Cop::Base
MSG = 'Avoid using `sleep` in production code.'
RESTRICT_ON_SEND = [:sleep].freeze
def on_send(node)
return unless node.method_name == :sleep
add_offense(node, message: MSG)
end
def on_block(node)
return unless node.send_node.method_name == :sleep
add_offense(node, message: MSG)
end
end
end
Advanced configuration includes cop inheritance, shared configurations, and conditional enabling based on Ruby version or gems present. Use inherit_from
to include external configuration files and inherit_mode
to control merge behavior.
# .rubocop.yml with inheritance
inherit_from:
- .rubocop_todo.yml
- config/rubocop_shared.yml
inherit_mode:
merge:
- Exclude
- Include
AllCops:
TargetRubyVersion: 3.1
SuggestExtensions: false
# Conditional cop configuration
Style/FrozenStringLiteralComment:
Enabled: true
EnforcedStyle: always
SupportedStyles:
- always
- never
Department-level configuration applies settings to multiple related cops simultaneously. Configure entire departments through Department/All
syntax or create custom departments for organization-specific rule groupings.
# Department configuration
Layout:
Enabled: true
Style/All:
Exclude:
- 'spec/**/*'
- 'test/**/*'
Lint:
Severity: error
Metrics/All:
Exclude:
- 'db/migrate/**/*'
Complex pattern matching in custom cops uses RuboCop's node pattern DSL for sophisticated AST analysis. Define patterns using def_node_matcher
and def_node_search
macros for reusable node detection logic.
class ComplexPatternCop < RuboCop::Cop::Base
extend AutoCorrector
MSG = 'Use specific exception classes instead of StandardError.'
def_node_matcher :raises_standard_error?, <<~PATTERN
(send nil? :raise (const nil? :StandardError) ...)
PATTERN
def on_send(node)
return unless raises_standard_error?(node)
add_offense(node) do |corrector|
corrector.replace(node.arguments.first, 'RuntimeError')
end
end
end
Production Patterns
Continuous Integration integration requires careful RuboCop configuration to balance code quality enforcement with development velocity. Configure RuboCop to run as part of CI pipelines while handling incremental adoption and legacy code exceptions.
# .github/workflows/rubocop.yml
name: RuboCop
on: [push, pull_request]
jobs:
rubocop:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.1
bundler-cache: true
- run: bundle exec rubocop --parallel --format github
Team workflow integration involves establishing RuboCop TODO files for gradual improvement and consistent developer environment setup. Use rubocop --auto-gen-config
to generate TODO files that exclude existing violations while enforcing rules for new code.
# Generated .rubocop_todo.yml
# This configuration was generated by
# `rubocop --auto-gen-config`
Metrics/AbcSize:
Exclude:
- 'app/controllers/admin/reports_controller.rb'
- 'lib/data_processor.rb'
Style/Documentation:
Exclude:
- 'app/models/legacy_user.rb'
- 'spec/**/*'
# Set target for gradual improvement
Metrics/LineLength:
Max: 100 # Decrease from current 120 over time
Editor integration streamlines development workflow through real-time feedback and automatic correction on save. Configure editors to run RuboCop on file save or provide inline violation display during coding.
# VS Code settings.json
{
"ruby.rubocop.onSave": true,
"ruby.rubocop.configFilePath": ".rubocop.yml",
"editor.formatOnSave": true,
"ruby.format": "rubocop"
}
# Vim configuration with ALE
let g:ale_linters = {'ruby': ['rubocop']}
let g:ale_fixers = {'ruby': ['rubocop']}
let g:ale_ruby_rubocop_options = '--display-cop-names'
let g:ale_fix_on_save = 1
Large codebase strategies involve incremental adoption, selective enabling, and performance optimization. Configure RuboCop to focus on specific file patterns or directories while excluding generated code and vendor dependencies.
# Incremental adoption strategy
AllCops:
Include:
- 'app/**/*.rb'
- 'lib/**/*.rb'
Exclude:
- 'vendor/**/*'
- 'db/schema.rb'
- 'config/routes.rb'
- 'bin/**/*'
# Performance optimization
AllCops:
UseCache: true
MaxFilesInCache: 50000
CacheRootDirectory: '/tmp'
# Enable only critical cops initially
Style/All:
Enabled: false
Lint/All:
Enabled: true
Layout/TrailingWhitespace:
Enabled: true
Performance & Memory
RuboCop performance optimization becomes critical on large codebases where analysis time impacts development workflow. Enable caching, parallel execution, and selective cop running to reduce analysis time from minutes to seconds.
Cache configuration stores analysis results between runs, dramatically improving performance for unchanged files. The cache stores file modification times, checksums, and previous analysis results in a local directory structure.
# Performance-optimized configuration
AllCops:
UseCache: true
CacheRootDirectory: tmp/rubocop_cache
MaxFilesInCache: 100000
# Enable parallel processing
bundle exec rubocop --parallel
File exclusion patterns prevent RuboCop from analyzing irrelevant files, reducing memory usage and execution time. Exclude generated files, vendor code, and test fixtures that don't require style enforcement.
# .rubocop.yml exclusion patterns
AllCops:
Exclude:
- 'vendor/**/*'
- 'node_modules/**/*'
- 'db/schema.rb'
- 'db/structure.sql'
- 'coverage/**/*'
- 'tmp/**/*'
- 'log/**/*'
- 'public/assets/**/*'
- '*.gemspec'
Memory usage optimization involves configuring garbage collection and limiting concurrent processes. Large codebases may require Ruby GC tuning and process memory limits to prevent system resource exhaustion.
# Environment variables for memory optimization
export RUBY_GC_HEAP_INIT_SLOTS=600000
export RUBY_GC_HEAP_FREE_SLOTS=600000
export RUBY_GC_HEAP_GROWTH_FACTOR=1.25
export RUBY_GC_HEAP_GROWTH_MAX_SLOTS=300000
# Limited parallel execution
bundle exec rubocop --parallel --fail-level warn
Selective cop execution reduces analysis time by running only relevant cops for specific scenarios. Use --only
and --except
flags to target specific violations or run lightweight cops during development.
# Fast feedback during development
alias rubocop-fast='bundle exec rubocop --only Style/TrailingWhitespace,Layout/TrailingBlankLines,Style/TrailingCommaInLiteral'
# Security-focused analysis
alias rubocop-security='bundle exec rubocop --only Lint/SecurityCop,Lint/UnreachableCode,Lint/UselessAssignment'
# Metrics-only analysis for code review
bundle exec rubocop --only Metrics --format json > metrics_report.json
Common Pitfalls
Configuration inheritance creates subtle behavior where multiple configuration files merge unexpectedly, causing cops to behave differently than intended. RuboCop searches parent directories for configuration files and merges them hierarchically.
# Problem: Unexpected cop enabling
# Parent directory .rubocop.yml
Style/Documentation:
Enabled: true
# Current directory .rubocop.yml
Style/StringLiterals:
EnforcedStyle: single_quotes
# Documentation cop still enabled despite expectations
Auto-correction safety varies significantly between cops, with some corrections changing code semantics rather than just formatting. Review auto-corrected changes carefully, especially for cops marked as unsafe corrections.
# Unsafe auto-correction example
# Original code
def calculate(items)
items.map { |item| item.price * item.quantity }
.reduce(:+) || 0
end
# RuboCop suggests Style/SafeNavigation
def calculate(items)
items.map { |item| item.price * item.quantity }
.reduce(:+) || 0 # This change could alter behavior
end
Cop conflicts occur when multiple cops suggest contradictory changes to the same code, creating endless correction cycles. Common conflicts involve string quoting, line length, and method complexity cops.
# Conflicting cops example
very_long_method_name_that_exceeds_line_length(
parameter_one: "single quotes",
parameter_two: 'mixed quotes cause conflicts'
)
# Metrics/LineLength wants shorter lines
# Style/StringLiterals wants consistent quotes
# Layout/MultilineMethodCallIndentation wants specific formatting
False positive violations appear when RuboCop misinterprets code context or domain-specific patterns. Configure cop exclusions for legitimate code patterns that violate style guides for valid reasons.
# False positive: Metrics/AbcSize in DSL code
class ApiEndpoint
# This pattern triggers complexity warnings
# but represents clean DSL usage
post '/users' do
validate_params(params)
authenticate_request
authorize_action(:create)
sanitize_input(params)
create_user(params)
render_response(user)
log_activity(user)
send_notifications(user)
update_metrics(:user_created)
end
end
# Solution: Exclude DSL patterns
Metrics/AbcSize:
Exclude:
- 'app/api/**/*'
Version compatibility issues arise when RuboCop cops target newer Ruby versions than the project supports, causing syntax errors or unavailable method suggestions. Configure TargetRubyVersion
to match project requirements.
# .rubocop.yml version configuration
AllCops:
TargetRubyVersion: 2.7 # Match project Ruby version
NewCops: disable # Prevent new cops in updates
# Cop-specific version requirements
Style/HashEachMethods:
Enabled: true
VersionAdded: 0.80
VersionChanged: 0.90
Safe: true
Reference
Core Commands
Command | Parameters | Description |
---|---|---|
rubocop |
[files/dirs] |
Analyze specified files or current directory |
rubocop --auto-correct |
[files] |
Apply safe automatic corrections |
rubocop --auto-correct-all |
[files] |
Apply all automatic corrections including unsafe |
rubocop --only COP_NAME |
cop_name |
Run only specified cops |
rubocop --except COP_NAME |
cop_name |
Run all cops except specified |
rubocop --parallel |
none | Enable parallel processing |
Configuration Options
Option | Type | Default | Description |
---|---|---|---|
TargetRubyVersion |
String | Latest | Ruby version for compatibility |
UseCache |
Boolean | true | Enable result caching |
CacheRootDirectory |
String | tmp/rubocop_cache |
Cache storage location |
NewCops |
String | pending |
How to handle new cops in updates |
SuggestExtensions |
Boolean | true | Suggest RuboCop extensions |
MaxFilesInCache |
Integer | 20000 | Maximum cached files |
Cop Departments
Department | Focus | Example Cops |
---|---|---|
Layout |
Code formatting | LineLength , IndentationWidth , TrailingWhitespace |
Style |
Code style | StringLiterals , Documentation , GuardClause |
Lint |
Potential bugs | UnusedVariable , ShadowingOuterLocalVariable |
Metrics |
Code complexity | AbcSize , CyclomaticComplexity , LineLength |
Naming |
Naming conventions | MethodName , ConstantName , VariableName |
Security |
Security issues | Eval , MarshalLoad , YAMLLoad |
Severity Levels
Level | Exit Code | Description |
---|---|---|
info |
0 | Informational messages |
refactor |
1 | Code improvement suggestions |
convention |
1 | Style guide violations |
warning |
1 | Potential problems |
error |
1 | Definite problems |
fatal |
2 | Syntax errors, crashes |
Output Formats
Format | Description | Use Case |
---|---|---|
simple |
Human-readable text | Development |
json |
JSON structure | Tool integration |
junit |
JUnit XML | CI systems |
github |
GitHub Actions | GitHub workflows |
clang |
Clang-style format | Editor integration |
emacs |
Emacs compilation | Emacs integration |
Auto-Correction Safety
Safety Level | Description | Command Flag |
---|---|---|
Safe | No semantic changes | --auto-correct |
Unsafe | Potential semantic changes | --auto-correct-all |
Safe only | Force safe corrections only | --safe-auto-correct |
Configuration Inheritance
Method | Behavior | Example |
---|---|---|
inherit_from |
Include external configs | inherit_from: .rubocop_shared.yml |
inherit_mode |
Control merge behavior | inherit_mode: { merge: [Exclude] } |
Directory traversal | Search parent directories | Automatic upward search |
Common Cop Parameters
Parameter | Type | Description | Example |
---|---|---|---|
Enabled |
Boolean | Enable/disable cop | Enabled: false |
Severity |
String | Override severity level | Severity: warning |
Exclude |
Array | File patterns to skip | Exclude: ['spec/**/*'] |
Include |
Array | File patterns to check | Include: ['**/*.rake'] |
Max |
Integer | Maximum threshold | Max: 120 |
EnforcedStyle |
String | Style variation | EnforcedStyle: single_quotes |